Spring AOP 的源码流程是怎样的?

我会将整个流程分解为几个关键阶段,并指出每个阶段的核心类和方法。

核心脉络:Bean 的生命周期与 BeanPostProcessor

Spring AOP 的所有操作都发生在 Bean 的创建和初始化过程中。其核心的钩子是 BeanPostProcessor 接口,它允许我们在 Bean 初始化前后对其进行干预和“包装”。

整个流程可以概括为:

  1. 启动与注册@EnableAspectJAutoProxy 注册了一个关键的 BeanPostProcessor
  2. 拦截 Bean 创建:这个 BeanPostProcessor 会拦截容器中每一个 Bean 的创建过程。
  3. 寻找切面与通知:对于每个 Bean,它会检查是否存在可以应用于该 Bean 的切面(Advisor)。
  4. 创建代理:如果找到了适用的切面,它就会为这个 Bean 创建一个代理对象(Proxy),并将所有切面逻辑织入其中。
  5. 返回代理:最终,返回给容器并注入到其他地方的是这个代理对象,而不是原始对象。

源码流程详解

阶段一:AOP 的启用与准备
  1. 入口: @EnableAspectJAutoProxy

    • 这个注解是我们开启 AOP 功能的开关。通过 @Import(AspectJAutoProxyRegistrar.class),它向 Spring 容器中注册了一个名为 AnnotationAwareAspectJAutoProxyCreator 的 Bean。
  2. 核心角色: AnnotationAwareAspectJAutoProxyCreator

    • 这个类是整个 AOP 流程的总指挥
    • 它本身就是一个 BeanPostProcessor,所以它能够监视和干预所有 Bean 的创建。
    • 它的父类 AbstractAutoProxyCreator 实现了核心的代理创建逻辑。
阶段二:拦截 Bean 初始化,决定是否代理

这个阶段发生在每个 Bean 实例化并完成属性填充之后,初始化方法(如 init-method@PostConstruct)调用之前或之后

  1. 关键方法: AbstractAutoProxyCreator.postProcessAfterInitialization()

    • 当一个 Bean(比如 UserService)完成初始化后,Spring 容器会调用这个方法。
    • 这个方法是决定是否要为当前 Bean 创建代理的决策点
    • 其内部会调用 wrapIfNecessary(bean, beanName, cacheKey) 方法。
    // AbstractAutoProxyCreator.java
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            // ...
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
        return bean;
    }
    
阶段三:寻找匹配的通知 (Advisors)

wrapIfNecessary 方法中,最关键的一步是为当前的 Bean 找到所有可以应用的“增强器”(在源码中称为 Advisor)。一个 Advisor 是 Advice(通知)和 Pointcut(切点)的结合体。

  1. 关键方法: getAdvicesAndAdvisorsForBean()

    • 这个方法负责扫描所有已知的 @Aspect 切面,解析它们的 @Pointcut 表达式。
    • 它会检查每个切点的表达式是否与当前 Bean 的方法匹配。
  2. 切面解析器: BeanFactoryAspectJAdvisorsBuilder

    • 这个类负责找到所有被 @Aspect 注解的 Bean,并把它们的方法(如 @Before, @Around)解析、包装成一个个 Advisor 对象。
  3. 决策

    • 如果 getAdvicesAndAdvisorsForBean() 返回的 Advisor 列表是空的,意味着没有切面逻辑需要应用到这个 Bean 上。wrapIfNecessary 方法会直接返回原始的 Bean 对象
    • 如果列表不为空,那么代理创建流程正式开始。
阶段四:创建 AOP 代理对象

如果确定需要创建代理,wrapIfNecessary 方法会调用 createProxy()

  1. 核心方法: createProxy()

    • 这个方法是创建代理对象的入口。
  2. 代理工厂: ProxyFactory

    • createProxy() 方法会创建一个 ProxyFactory 对象。
    • 它会将目标对象 (Target Bean)、所有找到的 Advisors 以及目标对象实现的接口等信息都设置到这个 ProxyFactory 中。
    • ProxyFactory 就像一个组装代理对象的工厂。
  3. 选择代理方式: DefaultAopProxyFactory

    • ProxyFactory 内部会使用 DefaultAopProxyFactory 来决定到底使用 JDK 动态代理还是 CGLIB。
    • 决策逻辑(在 createAopProxy 方法中):
      • 检查 proxy-target-class 配置是否为 true
      • 或者检查目标对象是否没有实现任何接口。
      • 如果满足任一条件,就选择 CGLIB (ObjenesisCglibAopProxy)。
      • 否则,选择 JDK 动态代理 (JdkDynamicAopProxy)。
  4. 生成代理

    • JdkDynamicAopProxyCglibAopProxy 会调用各自的底层 API(Proxy.newProxyInstance()Enhancer.create()) 来生成最终的代理对象。
    • 这个代理对象内部持有了所有需要执行的通知链。
阶段五:执行代理方法和通知链

当外部代码调用代理对象的方法时,AOP 的运行时逻辑被触发。

  1. 入口: JdkDynamicAopProxy.invoke()CglibAopProxy.intercept()

    • 无论是哪种代理,调用都会被转发到这两个方法之一。
    • 这两个方法是代理逻辑的执行入口
  2. 获取通知链:

    • 它们会根据当前调用的方法,从所有 Advisors 中筛选出需要在此方法上执行的通知链(List of interceptors)。
  3. 执行链的“发动机”: ReflectiveMethodInvocation

    • Spring 会创建一个 ReflectiveMethodInvocation 对象,它封装了目标对象、目标方法、参数以及上一步获取的通知链。
    • 这个类有一个核心方法:proceed()
  4. proceed() 的递归调用:

    • 当你调用 proceed() 时,它并不会直接调用目标方法。
    • 它会从通知链中取出下一个通知(Interceptor),然后调用这个通知的 invoke() 方法,并将 ReflectiveMethodInvocation 自身作为参数传进去。
    • 每个通知(尤其是环绕通知)在执行完自己的前置逻辑后,又会调用传入的 invocation.proceed(),这样就把控制权交给了通知链中的下一个通知
    • 这个过程形成了一个递归调用链,就像剥洋葱一样,一层层地执行通知。
    • 当所有通知都执行完毕后,最后的 proceed() 调用才会真正通过反射去执行你的目标业务方法
    • 目标方法执行完毕后,结果会沿着调用链反向返回,每个通知的后置逻辑得以执行。

流程图总结

+---------------------------+
| @EnableAspectJAutoProxy |
+---------------------------+
          | 1. Registers
          v
+-------------------------------------------+
| AnnotationAwareAspectJAutoProxyCreator    |  (A BeanPostProcessor)
| (Implements BeanPostProcessor)            |
+-------------------------------------------+
          | 2. Intercepts every bean creation via postProcessAfterInitialization()
          v
+-------------------------------------------+
| For each bean (e.g., UserService)         |
|   - findEligibleAdvisors()                |
|     (Parses @Aspect beans)                |
+-------------------------------------------+
          | 3. Advisors found?
    (No)  |                | (Yes)
          v                v
+-----------------+    +--------------------------------+
| Return original |    | createProxy() using ProxyFactory |
| bean            |    +--------------------------------+
+-----------------+               | 4. Chooses JDK or CGLIB
                                  v
                          +------------------+
                          |  Proxy Object    |  --> 5. This proxy is returned and injected
                          +------------------+


--- Method Execution Flow ---

External Call -> Proxy.someMethod() -> JdkDynamicAopProxy.invoke() / CglibAopProxy.intercept()
                                        |
                                        v
                                  Create ReflectiveMethodInvocation (contains interceptor chain)
                                        |
                                        v
                                  invocation.proceed() -> Interceptor1.invoke()
                                                            |
                                                            v
                                                          invocation.proceed() -> Interceptor2.invoke()
                                                                                    |
                                                                                    v
                                                                                  ...
                                                                                    |
                                                                                    v
                                                                                  Target Method Execution
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值