TL;DR#
- @EnableAspectJAutoProxy 开启自动代理
- Context 启动会创建 AnnotationAwareAspectJAutoProxyCreator 的 BeanDefinition 放到「BeanFactory」中的「beanDefinitionMap」
- 创建的 bean 实例放到「BeanFactory」中的「singletonObjects」和「beanPostProcessors」
- 前置处理,扫描所有 Aspect,生成所有的 Advisor,放入缓存
- 在创建 Bean 流程中的「实例化 Bean 的前置处理阶段」,扫描所有
@Aspect
修饰的类,生成「Advisor (Advice + Pointcut)」列表,并缓存 advisorsCahce 中
- 在创建 Bean 流程中的「实例化 Bean 的前置处理阶段」,扫描所有
- 创建 Proxy Bean (JDK Proxy 或 cglib 实现)
- 一般情况,在创建 Bean 流程中的「初始化 bean 的后置处理阶段」,但是在「循环依赖」情况下,会提前 AOP,在「填充 bean 属性阶段」,提前创建 Proxy Bean
- 检查 Advisor 的 Pointcut 条件是否与 bean 对应类中任一方法「匹配」,存在匹配情况,若匹配放入 「eligibleAdvisors」 列表
- 若「eligibleAdvisors」列表不为空,说明需要 AOP,进而创建 Proxy Bean,放入「BeanFactory」
ProxyBean
->AopProxy (JDK or Cglib)
->ProxyFacotry (advised)
->eligibleAdvisors
- Proxy Bean 调用代理方法,调用「拦截器链」链式执行「Advice」的方法
- 获取「Target Bean」和被调用方法所匹配的「拦截器链 (
Advisor
<->MethodInterceptor
)」 - 通过创建 ReflectiveMethodInvocation 实例,递归调用 proceed 方法,遍历「拦截器链」,进行反射调用「拦截器」的 Advice 方法
- ReflectiveMethodInvocation 实例通过维护 currentInterceptorIndex 索引来遍历「拦截器链」,当遍历完「拦截器链」会调用 invokeJoinpoint 方法,调用「Target Bean」的目标方法。
- 获取「Target Bean」和被调用方法所匹配的「拦截器链 (
什么是 AOP?#
- AOP (Aspect Oriented Programming, 面向切面编程) 是一种「编程范式」
- 本质是将「核心功能」与「切面功能」进行「解耦」,可分别独立进行开发功,然后将「核心功能」和「切面功能」进行「织入 Weaving」
什么是 Spring AOP?#
- 结合 Spring IOC 容器,通过在创建 Bean 过程中进行增强,生成 Proxy Bean,实现在程序 Runtime 期间,「动态」地将「核心功能」和「切面功能」进行「织入 Weaving」
- 本质就是,通过「代理模式 (动态代理)」实现 AOP,并结合 Spring IOC 容器,存放 Proxy Bean
相关概念#
- Jointpoint: 连接点 (方法执行,异常处理)
- Pointcut: 切点
- Advice: 在 Jointpoint 执行的「切面功能」操作
也叫「通知」,包括 Around, Before, After, AfterReturning, AfterThrowing
- Advisor: Pointcut + Advice
Spring AOP 的工作流程#
-
开启 AspectJ 注解自动代理
生成 AnnotationAwareAspectJAutoProxyCreator 的 bean 实例,放入「BeanFactory」中的「beanDefinitionMap」,「singletonObjects」和「beanPostProcessors」
- Spring AOP 开启 AspectJ 自动代理对应的注解是
@EnableAspectJAutoProxy
,通过注解@Import
导入 AspectJAutoProxyRegistrar - AspectJAutoProxyRegistrar 作用是将 AnnotationAwareAspectJAutoProxyCreator 生成对应的 BeanDefinition 对象,放入到 BeanDefinition 注册中心中
- AnnotationAwareAspectJAutoProxyCreator
- 根据 BeanDefinition 创建 AnnotationAwareAspectJAutoProxyCreator 的 Bean 对象,并加入到 BeanFactory 的 beanPostProcessors (Bean 处理器列表) 中
- 实现了 SmartInstantiationAwareBeanPostProcessor 接口,重要的方法如下
- Bean 初始化前置处理方法: postProcessBeforeInitialization()
- 获取早期 Bean 引用: getEarlyBeanReference()
- Bean 初始化后置处理方法: postProcessAfterInitialization()
- Spring AOP 开启 AspectJ 自动代理对应的注解是
-
前置准备
查找所有「切面 Aspect」类来生成「Advisor (Advice + Pointcut)」列表,并缓存起来
- 在创建 Bean 的流程,在「实例化 Bean」之前的阶段 「resolveBeforeInstantiation」
- 在第一次调用 AnnotationAwareAspectJAutoProxyCreator 的 bean 实例的postProcessBeforeInstantiation 方法
- 从「BeanFacotry」中获取所有的 Bean Name,遍历 Bean Name 列表,根据 beanName 查询「beanDefinitonMap」对应的类,是否含有
@Aspect
注解 - 对含有
@Aspect
的类,扫描其所有的「Advice」方法和对应的「Pointcut」方法,生成「Advisor」列表 - 将「Advisor」列表缓存到
advisorCache
Map 中
- 从「BeanFacotry」中获取所有的 Bean Name,遍历 Bean Name 列表,根据 beanName 查询「beanDefinitonMap」对应的类,是否含有
-
创建 Proxy Bean
若在创建 Bean 过程,与「Advisor」集合任意匹配成功,创建 AOP 代理对象
-
一般情况下,进行 AOP 创建 Proxy Bean,是在「初始化 bean 后置处理阶段」
- 在创建 bean 流程的「初始化 bean 后置处理阶段」
- 调用 AnnotationAwareAspectJAutoProxyCreator 的 bean 实例的 postProcessAfterInitialization 方法,调用 wrapIfNecessary 方法创建 Proxy Bean
- 从「advisorsCache」获取所有的 Advisor,通过查看当前需要创建的 bean 的类中,是否有任一方法与「Advisor 的 Pointcut 条件」匹配,从而筛选出匹配的「eligibleAdvisors」列表
- 创建 ProxyFactory 实例
- 将「匹配 advisor 列表」设置到 ProxyFactory 的「advisors」属性中
- 将包装了「实例化的 bean」的 SingletonTargetSource 实例设置到 ProxyFactory 的「targetSource」属性中
- 调用 ProxyFactory 实例的 createAopProxy 方法,根据条件选择创建 AopProxy 实例
- 「JdkDynamicAopProxy」
- 「ObjenesisCglibAopProxy」
- 调用 Aop Proxy 实例的 getProxy 方法的实现 (JDK 或 Cglib),创建「Proxy Bean」
- 将 Proxy Bean 放入到「BeanFactory 容器」的「singletonObjects」中
-
在有「循环依赖」下,需提前进行 AOP,提前创建 Proxy Bean,是在「填充 bean 属性阶段」
Mermaid Loading...- 在创建 bean 流程的「填充 bean 属性阶段」
- 调用 AnnotationAwareAspectJAutoProxyCreator 的 bean 实例的 getEarlyBeanReference 方法,进行提前 AOP,调用 wrapIfNecessary 方法创建 Proxy Bean
- 创建 Proxy Bean 与一般情况一样,详情看上述一般情况
-
-
Proxy Bean 调用代理方法,调用「拦截器链」链式执行「Advice」方法
- 调用 Proxy Bean 实例的方法,调用代理方法
- JDK 代理,调用的是 JdkDynamicAopProxy (InvocationHandler) 的 invoke 方法
- Cglib 代理,调用的是 ObjenesisCglibAopProxy 的 intercept 方法
- 从 advised (即 ProxyFactory) 中取出「原始 Bean (Target Bean)」
- 构建与「被调用方法 callee method」所匹配的「拦截器链」
- 从 advised (即 ProxyFactory) 中的与 bean 的类所匹配的所有的 「Advisor」
- 然后遍历检查「Advisor」是否与当前方法匹配
- 与当前方法匹配的「Advisor」,进行构建出对应的「Interceptor 拦截器」,放入「拦截器链」列表中
- 缓存和返回「拦截器链」
- 构建 MethodInvocation,包装 Proxy Bean, Target Bean, 「拦截器链」等,执行「拦截器链」
- 根据不同代理创建不同的 MethodInvocation,递归调用 proceed 方法
- JDK 代理,创建 ReflectiveMethodInvocation,进行递归调用 ReflectiveMethodInvocation 的 proceed 方法
- Cglib 代理,创建 CglibMethodInvocation,进行递归调用 ReflectiveMethodInvocatio 的 proceed 方法 (CglibMethodInvocation 继承了 ReflectiveMethodInvocatio)
- 通过反射调用「拦截器」的 Advice 方法
- ReflectiveMethodInvocation 实例通过维护 currentInterceptorIndex 索引来遍历「拦截器链」
- 如果已执行完「拦截器链」,调用 ReflectiveMethodInvocatio 的 invokeJoinpoint 方法,反射调用「原始 Bean (Target Bean)」的方法 (被代理)
- 根据不同代理创建不同的 MethodInvocation,递归调用 proceed 方法
- 调用 Proxy Bean 实例的方法,调用代理方法
拦截器与 Advice 和注解的关系#
@Around
- Advice 和拦截器: AspectJAroundAdvice
@Before
- 适配器: MethodBeforeAdviceAdapter
- Advice: AspectJMethodBeforeAdvice->MethodBeforeAdvice
- 拦截器: MethodBeforeAdviceInterceptor
@After
- Advice 和拦截器: AspectJAfterAdvice
@AfterReturning
- 适配器: MethodBeforeAdviceAdapter
- Advice: AspectJAfterReturningAdvice->AfterReturningAdvice
- 拦截器: AfterReturningAdviceInterceptor
@AfterThrowing
- Advice 和拦截器: AspectJAfterThrowingAdvice
- ThrowsAdviceAdapter 适配器,没有对应的注解
- Advice: ThrowsAdvice
- 拦截器: ThrowsAdviceInterceptor
「拦截器链」执行过程的时序图#
Mermaid Loading...