Spring AOP 注解开启全流程源码解析:从 <aop:aspectj-autoproxy/>
到代理生成
Spring AOP 注解功能(如 @Aspect
、@Before
)的开启依赖 <aop:aspectj-autoproxy/>
配置,其底层是一套 “自定义标签解析→核心处理器注册→BeanPostProcessor 介入→AOP 代理生成” 的完整链路。从 “自定义标签解析”“核心处理器初始化”“BeanPostProcessor 调用时机”“AOP 代理生成” 四个维度,逐行拆解 AOP 注解开启的底层逻辑。
前置知识:Spring 自定义标签解析机制
<aop:aspectj-autoproxy/>
并非 Spring 内置的 “默认标签”(如 <bean>
、<import>
),而是自定义标签。Spring 解析自定义标签需依赖两个核心配置文件和一套解析流程:
自定义标签的核心配置文件
Spring 通过类路径下的 META-INF/spring.handlers
和 META-INF/spring.schemas
关联自定义标签与解析逻辑:
spring.handlers
:映射 “命名空间(namespace)” 到 “标签处理器(NamespaceHandler)”,告诉 Spring 用哪个类解析该命名空间下的标签;spring.schemas
:映射 “XSD Schema 地址” 到 “本地 XSD 文件”,用于校验自定义标签的语法合法性。
示例:AOP 自定义标签的配置
1 | # spring.handlers:aop 命名空间对应 AopNamespaceHandler |
自定义标签的解析流程
当 Spring 解析 XML 配置遇到自定义标签(如 <aop:aspectj-autoproxy/>
)时,执行以下步骤:
- 提取命名空间:从标签的
xmlns:aop
属性获取命名空间(http://www.springframework.org/schema/aop
); - 获取处理器:通过
NamespaceHandlerResolver
从spring.handlers
中找到对应的AopNamespaceHandler
; - 初始化处理器:调用
AopNamespaceHandler.init()
注册标签解析器; - 解析标签:根据标签名称(
aspectj-autoproxy
)调用对应的解析器(AspectJAutoProxyBeanDefinitionParser
)。
源码印证:
1 | // 1. 提取命名空间,获取对应的 NamespaceHandler |
步骤 1:AopNamespaceHandler 初始化与解析器注册
AopNamespaceHandler
是 AOP 自定义标签的总处理器,其 init()
方法会注册不同标签对应的解析器,核心是为 <aop:aspectj-autoproxy/>
绑定 AspectJAutoProxyBeanDefinitionParser
。
1. AopNamespaceHandler#init () 源码解析
1 | public void init() { |
- 关键逻辑:
registerBeanDefinitionParser("aspectj-autoproxy", ...)
为<aop:aspectj-autoproxy/>
标签绑定了解析器AspectJAutoProxyBeanDefinitionParser
,后续该标签的解析由这个类完成。
步骤 2:AspectJAutoProxyBeanDefinitionParser 解析标签 —— 注册核心处理器
AspectJAutoProxyBeanDefinitionParser
的核心作用是:解析 <aop:aspectj-autoproxy/>
标签,并向 IOC 容器注册 AnnotationAwareAspectJAutoProxyCreator
(AOP 注解功能的核心处理器)。
1. 核心解析逻辑:registerAspectJAnnotationAutoProxyCreatorIfNecessary
1 | class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser { |
关键方法:AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary
该方法的作用是 “确保容器中存在 AnnotationAwareAspectJAutoProxyCreator
的 BeanDefinition”,若已存在则不重复注册,同时处理标签的属性(如 proxy-target-class
):
1 | public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( |
proxy-target-class
属性:若设为true
,Spring 会强制使用 CGLIB 代理(即使目标类实现接口);默认false
,优先使用 JDK 动态代理。
2. AnnotationAwareAspectJAutoProxyCreator:AOP 注解的核心处理器
AnnotationAwareAspectJAutoProxyCreator
是 Spring AOP 注解功能的 “大脑”,其类结构决定了它的核心能力:
BeanPostProcessor
:允许它在 Bean 实例化、初始化前后介入,核心是postProcessAfterInitialization()
方法中生成 AOP 代理;BeanFactoryAware
:允许它获取BeanFactory
,用于扫描容器中的@Aspect
切面类和增强方法(如@Before
、@After
)。
步骤 3:BeanPostProcessor 的调用时机 ——AOP 代理的介入点
AnnotationAwareAspectJAutoProxyCreator
实现了 BeanPostProcessor
接口,Spring 会在 Bean 初始化阶段 调用其 postProcessBeforeInitialization()
和 postProcessAfterInitialization()
方法,其中 postProcessAfterInitialization()
是生成 AOP 代理的核心时机。
1. BeanPostProcessor 的调用链路
Spring 在 doCreateBean()
(Bean 创建的核心方法)中,通过 initializeBean()
调用 BeanPostProcessor:
1 | // doCreateBean() 中触发 Bean 初始化 |
initializeBean ():BeanPostProcessor 的调用入口
1 | protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) { |
- 关键结论:
AnnotationAwareAspectJAutoProxyCreator
的postProcessAfterInitialization()
方法在 Bean 初始化完成后调用,此时 Bean 已实例化且属性注入完成,是生成 AOP 代理的最佳时机。
2. 核心方法:postProcessAfterInitialization () 与 wrapIfNecessary ()
AnnotationAwareAspectJAutoProxyCreator
继承自 AbstractAutoProxyCreator
,其 postProcessAfterInitialization()
方法最终调用 wrapIfNecessary()
,该方法是判断是否生成代理、如何生成代理的核心。
wrapIfNecessary () 源码解析
1 | protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { |
关键步骤拆解
(1)isInfrastructureClass ():跳过内部基础设施 Bean
1 | protected boolean isInfrastructureClass(Class<?> beanClass) { |
- 原因:
@Aspect
切面类本身是 “增强器的定义者”,而非 “被代理的目标”,因此无需为其生成代理。
(2)getAdvicesAndAdvisorsForBean ():查找匹配的增强器
该方法的核心是 “从容器中找到所有能应用到当前 Bean 的增强器(Advisor)”,分为两步:
- 查找所有候选增强器:扫描容器中
@Aspect
切面类的增强方法(如@Before
标注的方法),封装为Advisor
; - 筛选匹配的增强器:根据切入点(Pointcut)判断增强器是否适用于当前 Bean 的方法。
源码印证:
1 | protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { |
findCandidateAdvisors()
:AnnotationAwareAspectJAutoProxyCreator
重写了该方法,会额外扫描@Aspect
切面类的增强方法(通过aspectJAdvisorsBuilder.buildAspectJAdvisors()
)。
(3)createProxy ():生成 AOP 代理
当找到匹配的增强器后,createProxy()
会通过 ProxyFactory
生成代理对象,代理类型(JDK/CGLIB)由 proxy-target-class
属性和目标类类型决定:
1 | protected Object createProxy( |
- 代理类型决策逻辑:与
ProxyFactoryBean
一致(参考之前的 ProxyFactoryBean 解析),优先根据proxy-target-class
配置,其次根据目标类是否实现接口。
特殊场景:循环依赖与 AOP 代理的协同
当存在循环依赖(如 A Setter 依赖 B,B Setter 依赖 A)且 Bean 需要 AOP 代理时,Spring 会通过 三级缓存 提前生成代理对象,确保依赖注入的是代理对象(而非原始对象)。
关键方法:getEarlyBeanReference ()
在 doCreateBean()
中,当 Bean 实例化后、属性注入前,若允许循环依赖,会调用 addSingletonFactory()
将 getEarlyBeanReference()
封装为 ObjectFactory
放入三级缓存:
1 | addSingletonFactory(beanName, new ObjectFactory<Object>() { |
getEarlyBeanReference()
由 AbstractAutoProxyCreator
实现,会调用 wrapIfNecessary()
提前生成代理:
1 | protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { |
- 核心作用:在循环依赖场景下,提前为 Bean 生成代理对象,确保依赖方注入的是代理对象,与最终放入一级缓存的代理对象一致。
总结:AOP 注解开启的完整链路
从 <aop:aspectj-autoproxy/>
配置到 AOP 代理生成,整个流程可精简为 6 步:
- XML 解析触发:Spring 解析 XML 时遇到
<aop:aspectj-autoproxy/>
自定义标签; - 自定义标签映射:通过
spring.handlers
找到AopNamespaceHandler
; - 解析器注册:
AopNamespaceHandler.init()
注册AspectJAutoProxyBeanDefinitionParser
; - 核心处理器注册:
AspectJAutoProxyBeanDefinitionParser
向容器注册AnnotationAwareAspectJAutoProxyCreator
; - BeanPostProcessor 介入:
AnnotationAwareAspectJAutoProxyCreator
在postProcessAfterInitialization()
中调用wrapIfNecessary()
; - 代理生成:
wrapIfNecessary()
查找匹配的增强器,通过ProxyFactory
生成 JDK/CGLIB 代理
v1.3.10