`

Spring AOP实现源码分析(三)

 
阅读更多


Spring AOP的实现可以分为三大部分
1. 注册AOP功能具体实现类

2. 普通Bean实例化时AOP的切入

3. AOP切入具体流程

 

AOP 切入有两个时机

1. 如果有循环依赖,就会 doCreateBean 时提前调用 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

2.如果没有循环依赖,正常情况下在 populateBean里调动

 

下面分析BeanPostProcessor执行过程中,aop如何切入,上一节讲到,普通bean初始化会调用如下方法

 

// 调用AOP的真正实现方法入口  
    result = beanProcessor.postProcessAfterInitialization(result, beanName); 
 aop此方法实际是继承自AbstractAutoProxyCreator, 跟踪一下 postProcessAfterInitialization的实现

 


 

创建代理实际只有两个步骤

1. 获取增强方法或者增强器

2. 根据获取到的增强器进行代理

	
// class 
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  if (bean != null) {
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (!this.earlyProxyReferences.contains(cacheKey)) {
        // 进行aop包装
        return wrapIfNecessary(bean, beanName, cacheKey);
      }
  }
  return bean;
}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
  // 1. 获取增强器, 下面会详细拆分
  Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
  // 如果获取到aop拦截器
  if (specificInterceptors != DO_NOT_PROXY) {
    this.advisedBeans.put(cacheKey, Boolean.TRUE);
    // 2. 创建代理
    Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    this.proxyTypes.put(cacheKey, proxy.getClass());
    // 最终返回aop代理类
    return proxy;
  }

 

首先跟踪 获取增强器 的逻辑

 

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
  // 封装在函数内
  List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
  if (advisors.isEmpty()) {
    return DO_NOT_PROXY;
  }
  return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
  // 获取增强器,其内部实现具体为以下步骤
  // 1. 获取beanFactory所有的beanName
  // 2. 遍历所有beanName,找到声明为AspectJ的类
  // 3. 对第二步的类,进行增强器提取
  // 4. 将提取结果加入缓存(提升下次调用的的效率,因为每个bean都会走这个流程)
  // 增强器实际会根据method上的注解(Before, After...)初始化不同的类,比如 Before 注解对应 AspectJMethodBeforeAdvice
  List<Advisor> candidateAdvisors = findCandidateAdvisors();
  // 判断当前bean可用的增强器,因为不一定所有的增强器对当前bean适用
  List<Advisor> eligibleAdvisors = 
  findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
  extendAdvisors(eligibleAdvisors);
  if (!eligibleAdvisors.isEmpty()) {
    eligibleAdvisors = sortAdvisors(eligibleAdvisors);
  }
  return eligibleAdvisors;
}
 
继续跟踪 创建代理 实现  

 

protected Object createProxy(
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
......
  // 统一处理封装所有的的增强器
  Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
......
  // 生成代理,并返回,生成代理会有两种方式
  // 对于实现了接口的类,默认使用jdk动态代理; 对于没有实现接口的类,只能使用cglib
  // 对于实现了接口的类,可以强制使用cglib(通过配置proxy-target-class="true")
  return proxyFactory.getProxy(getProxyClassLoader());
}
 代理的真正实现调用过程(jdk动态代理,或者cglib)不再赘述,比如动态代理,最终会调用invoke,稍微看一下JdkDynamicAopProxy的invoke实现,内部通过chain保存了增强器调用链,实现过程类似于职责链设计模式

 

// class JdkDynamicAopProxy
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
......
   // 获取并封装调用链chain,实际会对advisor进行转换,比如 (@Before注解)AspectJMethodBeforeAdvice
 会转换为 MethodBeforeAdviceInterceptor
  List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
  if (chain.isEmpty()) {	
    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
  } else {
    // 代理方法执行
    invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    // 实际执行比较有意思,会loop chain,但是需要仔细看逻辑才明白
    retVal = invocation.proceed();
  }
......
}

public Object proceed() throws Throwable {
  // interceptorsAndDynamicMethodMatchers实际是上面的调用链chain,若到达队尾,则跳出
  if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    return invokeJoinpoint();
  }
  // 获取下一个interceptor
  Object interceptorOrInterceptionAdvice =			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
......
  // 这个方法,将this传了进去,里面的实现可以看出,实际在执行完当前interceptor的invoke方法后,接着执行this.proceed,即又调用回来了当前proceed方法,保证loop chain完成
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}

// 比如 MethodBeforeAdviceInterceptor 的实现
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
  // advice封装了advisor
  this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
  // mi即为上面的invoke方法传入的this
  return mi.proceed();
}
 
  • 大小: 73 KB
分享到:
评论

相关推荐

    AOP流程源码分析-SpringAOP中定义的类图

    AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析-SpringAOP中定义的类图AOP流程源码分析...

    Spring AOP实现 项目源码 Myeclipse 直接导入可用

    **三、项目源码分析** 项目的源码包含了一个简单的Spring AOP示例,可能包括以下几个部分: 1. `Aspect`类:包含了切面逻辑的类,通常有多个通知方法。 2. `Service`类:业务逻辑类,切面将会影响到的方法。 3. `...

    五、Spring源码分析——Spring Aop

    《Spring AOP 源码分析》 在深入探讨Spring AOP之前,我们先要理解AOP(面向切面编程)的基本概念。AOP是一种编程范式,它将关注点分离,使得我们可以将横切关注点(如日志、事务管理、安全检查等)与业务逻辑解耦...

    Spring AOP源码分析.mmap

    有关于Spring,我们最常用的两个功能就是IOC和AOP,前几篇文章从源码级别介绍了Spring容器如何为我们生成bean及bean之间的依赖关系... 确实,Spring也就是通过这两种方式来实现AOP相关功能,下面就通过源码来简单求证下

    Java spring AOP源码

    ### Java Spring AOP源码分析 #### 概述 在探讨Spring AOP源码之前,我们首先需要了解Spring AOP的基本概念以及它的工作原理。面向切面编程(Aspect-Oriented Programming, AOP)是一种编程范式,它通过将横切关注...

    Spring AOP框架实现的结构分析

    在本文中,我们将从实现的角度来认识 SpringAOP 框架,从外部接口、内部实现、组成部分、执行过程四个方面来介绍 Spring AOP 框架的结构分析。 最后,本文的目标是从实现的角度来认识 SpringAOP 框架,观察的角度是...

    spring-aop源码

    总结,Spring AOP源码的探索有助于开发者深入理解面向切面编程的实现机制,提升问题解决能力,从而更好地利用AOP技术优化和维护应用程序。通过实践与学习,我们可以更好地驾驭这个强大的工具,提高代码的可维护性和...

    spring源码--AOP流程--笔记.docx

    Spring AOP 源码分析笔记 Spring AOP(Aspect-Oriented Programming)是一种编程范式,它允许开发者 modularize cross-cutting concerns,即将横切关注点模块化。AOP 使得开发者可以将一些公共的功能模块化,以便在...

    Spring Aop 引用新功能 源码

    通过源码分析,我们可以深入了解Spring AOP的工作原理,以及如何通过`IntroductionInterceptor`或`@AspectJ`来实现引入。理解并熟练运用这一特性,将有助于我们在实际开发中更好地进行代码解耦和模块化,提升软件的...

    死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序.pdf

    在 Spring 中,AOP 的实现主要依赖于代理模式,有两种代理方式:JDK 动态代理和 CGLIB 动态代理。 JDK 动态代理是基于接口的,它要求被代理的目标对象必须实现至少一个接口。Spring 使用 `java.lang.reflect.Proxy`...

    spring-aop.pdf 源码电子书

    标题和描述中提到的是关于Spring AOP源码的电子书。Spring AOP(Aspect-Oriented Programming)是Spring框架的一个重要组成部分,它支持面向切面编程的实践,是为了解决面向对象编程中的横切关注点问题而设计的。在...

    springAOP核心组件分析.pdf

    Spring AOP(面向切面编程)是Spring框架的一个重要组成部分,它允许开发者将横切关注点与业务逻辑分离,实现业务逻辑的模块化。AOP核心组件包括几个关键概念,如切面(Aspect)、通知(Advice)、连接点(Joinpoint...

    Spring AOP介绍及源码分析

    **Spring AOP介绍** ...学习并掌握Spring AOP及其源码分析对于提升作为IT专业人员的技术水平至关重要,它不仅能够帮助我们编写更加优雅和简洁的代码,还能使我们更好地应对复杂的企业级应用需求。

    Java流行框架源码分析:Spring源码、SpringBoot源码、SpringAOP源码、SpringSecurity源码、

    Java流行框架源码分析:Spring源码、SpringBoot源码、SpringAOP源码、SpringSecurity源码、SpringSecurity OAuth2源码、JDK源码、Netty源码

    Spring AOP的底层实现技术

    9. **源码分析** 深入研究Spring AOP的源码,可以帮助我们更好地理解其工作原理,例如,可以查看`org.springframework.aop.framework.ProxyFactoryBean`、`org.springframework.aop.aspectj.autoproxy....

    Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现.doc

    在分析 Spring AOP 的源码之前,我们需要了解 Spring IOC 的初始化过程和 Bean 的生命周期等。AOP 是基于 IOC 的 Bean 加载来实现的,所以理解 Spring AOP 的初始化必须要先理解 Spring IOC 的初始化。 二、AOP ...

    Spring aop 性能监控器

    本篇文章将深入探讨如何使用Spring AOP实现性能监控器,并通过源码分析来理解其工作原理。 首先,我们要了解AOP的核心概念——切面(Aspect)、通知(Advice)、连接点(Join Point)、切入点(Pointcut)和织入...

    spring aop实现日志分析管理

    在Spring AOP(面向切面编程)中实现日志分析管理是一种常见的做法,它能帮助开发者跟踪和理解系统运行过程中的行为,同时提供详细的错误日志以支持运维工作。通过元注解的方式,我们可以轻松地将日志记录功能集成到...

    老王读spring-aop源码分析&amp;测试代码.zip

    老王读 Spring AOP 系列文章的源码分析&测试代码 帮助大家学习 Spring 源码,更加了解 Spring 的底层 博客专栏地址:https://blog.csdn.net/wang489687009/category_11269905.html

    spring aop实现日志功能

    标题"spring aop实现日志功能"涉及到的是如何利用Spring AOP来记录和跟踪应用程序中的操作,这对于调试、性能分析和故障排查至关重要。下面我们将详细探讨如何通过Spring AOP来实现日志功能。 首先,理解AOP的基本...

Global site tag (gtag.js) - Google Analytics