SpringBoot-AOP
组件了解
AbstractAutoProxyCreator
首先看类图:

AbstractAutoProxyCreator
最主要的类了,使用AOP创建代理的核心类。看一些成员变量:
protected static final Object[] DO_NOT_PROXY = null;不创建代理的返回protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];返回这个表示 只使用 commonAdvisor 就可以了private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();用来包装Advisor的,对各种类型的advisor做处理,某些需要特殊处理的,可以向里面注册AdvisorAdapter,用它来包装advisor具体可以看方法
AbstractAutoProxyCreator.buildAdvisors和DefaultAdvisorAdapterRegistry.warpprivate String[] interceptorNames = new String[0];设置common interceptor。默认是没有的。都是AdvisorapplyCommonInterceptorsFirst这个属性控制 是否应用 commonInterceptorprivate final Set<String> targetSourcedBeansprivate final Set<Object> earlyProxyReferencesprivate final Map<Object, Class<?>> proxyTypesprivate final Map<Object, Boolean> advisedBeans
还有很多重要的方法:
isInfrastructureClass(beanClass) 和 shouldSkip(beanClass, beanName) 这两个方法 是bean是否要被代理的重要判读依据
1 | // 如果是 Advice org.springframework.aop.Pointcut Advisor AopInfrastructureBean 的实现类,都是 aop的基础类,都不考虑 代理 |
ps: 暂时只有
AspectJAwareAdvisorAutoProxyCreator实现了 shouldSkip 方法,其他都没有,直接返回false,也就是不跳过任何类
protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource customTargetSource) 获取某个bean 的 Advice和Advisor
也是提供给子类的,BeanNameAutoProxyCreator 和 AbstractAdvisorAutoProxyCreator 实现了,他也只有这两个类,也就是提供了两种策略去匹配某个bean的advisor
先看看BeanNameAutoProxyCreator 根据BeanName筛选的 advisor:
1 |
|
就是根据配置的beanNames,看要被代理的beanName 是否满足正则匹配的筛选条件,但是只能创建 commonInterceptor 的代理。
再看看AbstractAdvisorAutoProxyCreator及他的子类等:
1 | // AbstractAdvisorAutoProxyCreator |
大致思路就是 找到 所有 Advisor,然后 看看这些 Advisor 是否可apply在 该bean上。
AbstractAdvisorAutoProxyCreator 的子类 AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator 也扩展了上面的几个方法:
1 | //AnnotationAwareAspectJAutoProxyCreator 类中的方法 |
还有 createProxy, SmartInstantiationAwareBeanPostProcessor的所有实现方法 等等 都在这里。
最后终于对这个类,以及一些子类了解些了,那么再看这些类的功能:
AbstractAutoProxyCreator: Spring 为Spring AOP 模块暴露的可扩展抽象类,也是 AOP 中最核心的抽象类。Nepxion Matrix 框架便是基于此类对AOP进行扩展和增强。BeanNameAutoProxyCreator: 根据指定名称创建代理对象(阿里大名鼎鼎的连接池框架druid也基于此类做了扩展)。通过设置 advisor,可以对指定的 beanName 进行代理。支持模糊匹配。AbstractAdvisorAutoProxyCreator: 功能比较强大,默认扫描所有Advisor的实现类。相对于根据Bean名称匹配,该类更加灵活。动态的匹配每一个类,判断是否可以被代理,并寻找合适的增强类,以及生成代理类。DefaultAdvisorAutoProxyCreator: AbstractAdvisorAutoProxyCreator的默认实现类。可以单独使用,在框架中使用AOP,尽量不要手动创建此对象。AspectJAwareAdvisorAutoProxyCreator: 支持了AspectJ注解,将@AspectJ注解的类中的@Before 等注解转换为 对应的Advisor,是Aspectj的实现方式,也是Spring Aop中最常用的实现方式,如果用注解方式,则用其子类AnnotationAwareAspectJAutoProxyCreator。AnnotationAwareAspectJAutoProxyCreator: 目前最常用的AOP使用方式。spring aop 开启注解方式之后,该类会扫描所有@Aspect()注释的类,生成对应的adviosr。目前SpringBoot框架中默认支持的方式,自动配置。ProxyConfig声明了 配置的Proxy一些属性,比如说 proxyTargetClass, exposeProxy 等。各个creator 都需要继承它AopInfrastructureBean就是一个标志性的接口,实现该接口表示 是 AOP的基础bean,在扫描创建代理过滤的时候,是要忽略的。isInfrastructureClass方法的一个判断就是 是否实现了这个接口。 一般都是 PostProcessor 和 Creator 实现该接口。
Advisor, Advice 与 Pointcut
org.springframework.aop.Advisor是spring提供的 用来整合aop切面数据的类。org.aopalliance.aop.Advice是aop提供的真正处理 代理逻辑的类。org.springframework.aop.Pointcutspring提供的,将ClassFilter, MethodMatcher整合到一起的类,用于在筛选bean。 这里说的是这个Pointcutorg.aspectj.lang.annotation.Pointcut就是在@Aspect使用的@Pointcut,标记一个 Pointcut 切点。org.aspectj.lang.reflect.PointcutaspectJ中的@Pointcut在aop 运行时的表示。
一般的一个 Advisor必须要能够获取Advice,PointcutAdvisor还可以获取 Spring的Pointcut。Advice作为此次aop的处理逻辑,Pointcut作为筛选条件,那些bean要被这个advice代理。
Advisor
上类图:
所有的都是PointcutAdvisor
分为三大块,InstantiationModelAwarePointcutAdvisor, AbstractGenericPointcutAdvisor, 其他。
InstantiationModelAwarePointcutAdvisor它有个唯一的实现,所有被@Aspect注解的类都会创建一个该类型的对象。AbstractGenericPointcutAdvisorAbs系列。这些可以自定义Advice, Pointcut,我们可以随便使用,系统也提供了一些常用的实现。比如说想通过正则来筛选被代理对象,就可以使用
RegexpMethodPointcutAdvisor,想通过methodName的就使用NameMatchMethodPointcutAdvisor。DefaultPointcutAdvisorAdvice 是 空,Pointcut 都返回true。构造方法可以传入这两个参数,最灵活,我们可以随便配置。
其他主要有StaticMethodMatcherPointcutAdvisor,StaticMethodMatcherPointcutAdvisor用来做基于静态方法的Advisor。使用的话直接实现MethodMatch的match方法,其实是StaticMethodMatcherPointcut的,也就是我们的筛选条件。Advice的话 是默认的 EMPTY_ADVICE。
Advice
上类图:
org.aopalliance.aop.Advice完整类名。是由AOP提供的该类,而且还提供了Interceptor 和 MethodInterceptor。
Advice是真正代理的逻辑所在的地方,所以类也多和相关业务相关。
AspectJ AOP相关业务。主要类有AspectJMethodBeforeAdvice, AspectJAfterReturningAdvice, AspectJAfterAdvice, AspectJAroundAdvice, ThrowingXXXAdvice。涉及的主要的类就是AbstractAspectJAdvice他们会针对特定的注解生成特定的Advice,在方法的执行过程中嵌入进去,并通过反射调用用户增加的逻辑。事务相关业务。有TransactionInterceptor。自定义Advice我们可以随便自定义Advice,使用自己的Advice。
与AspectJ业务相关的还有一个接口: AspectJPrecedenceInformation 主要提供了一些接口方法,返回一些信息,针对AspectJ相关的注解生成的Advice/Advisor, 能够方便的排序。
1 | public interface AspectJPrecedenceInformation extends Ordered { |
Pointcut
上类图:
Pointcut 就可以理解为筛选条件。通过ClassFilter 和 MethodMatcher
他也可以分为三大类:StaticMethodMatcherPointcut, AnnotationMatchingPointcut, ExpressionPointcut
StaticMethodMatcherPointcut根据方法筛选。具体通过实现MethodMatcher接口,通过他的match方法。他的classFilter默认就总返回trueAnnotationMatchingPointcut根据注解筛选。 构造方法的参数是Class Annotation 和 method Annotation。如果传了,就创建AnnotationClassFilter, AnnotationMethodMatcher。不传就是TRUE通过类图也可以看到
AnnotationMethodMatcher也是StaticMethodMatcher的一个子类ExpressionPointcut根据表达式筛选,就是针对AspectJ的execute表达式,而且产生的 MethodFilter 和 ClassFilter 都是实际通过调用 aspect包中的类来完成筛选的。
源码分析
自动装配-创建AnnotationAwareAspectJAutoProxyCreator
还是从AopAutoConfiguration 开始。
1 |
|
AopAutoConfiguration是AOP的自动装配类。根据配置选择不同的代理方式,默认选择支持 classProxy的 CglibAutoProxyConfiguration。 它又引入了注解@EnableAspectJAutoProxy, 该注解引入了ImportRegistrar – AspectJAutoProxyRegistrar,它最终注册了bean AnnotationAwareAspectJAutoProxyCreator。
@EnableAspectJAutoProxy也可以在主类上增加注解配置代理的方式和设置是否 exposeProxy。
定义 AnnotationAwareAspectJAutoProxyCreator
看AspectJAutoProxyRegistrar.registerBeanDefinitions
1 |
|
创建 AnnotationAwareAspectJAutoProxyCreator
就是createBean的流程,将beanDefinition 中定义的配置设置进去,比如常见的proxyTargetClass, exposeProxy等,都在ProxyConfig中。
创建好的AnnotationAwareAspectJAutoProxyCreator除了有之前设置好的属性外,还有几个成员对象。

BeanFactoryAdvisorRetrievalHelperAdapter辅助从BeanFactory中找Advisor
AbstractAdvisorAutoProxyCreator 重写了 setBeanFactory方法,并调用了initBeanFactory 方法,在这里面创建了 BeanFactoryAdvisorRetrievalHelperAdapter1
2
3
4
5
6
7
8
9
10
11// AbstractAdvisorAutoProxyCreator
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}
// 将 findCandidate的任务委托给 advisorRetrievalHelper,
// 实际就是扫描所有的bean,找到 Advisor 类型的
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
AspectJAdvisorFactory & BeanFactoryAspectJAdvisorsBuilder合作 解析 AspectJ 注解的类为 Advisor
AnnotationAwareAspectJAutoProxyCreator重写了initBeanFactory,又创建了两个对象,方便自己 找 AspectJ这样的Advisor
1 | // AnnotationAwareAspectJAutoProxyCreator |
找Advisor
找Advisor是父类 AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean提供的,但是具体的实现完全是子类完成的。
前面也说过,对于他的两大子类来说,
BeanNameAutoProxyCreator是比较简单的,如何BeanName 正则匹配设置好的mappedName,就会设置代理,但是 只会设置统一的代理。AbstractAdvisorAutoProxyCreator会先找出所有的Advisor,然后再根据当前bean去匹配Advisor,看是否这个Advisor匹配成功,成功的话就设置代理,没有一个成功的就不设置代理。出现多个匹配的Advisor,就会涉及到排序的问题,因为Advisor由spring管理,所有可以根据Order来排序。
AnnotationAwareAspectJAutoProxyCreatorAspectJ 系的,在扫描所有Advisor的时候,增加了扫描@AspectJ注解,并将其变成Advisor。因为
@Aspect注解的bean扫描出来之后的Advisor的order都是一样的,所以又专门提供了AspectJPrecedenceInformation接口,保存一些被@Aspect注解的生成的Advisor的元数据,比如说标识是 before 还是 after,方法的声明顺序等等。
首先看看扫描Advisor的过程,具体是由AbstractAdvisorAutoProxyCreator中的BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper代理完成的。
1 | /** |
再看看 AnnotationAwareAspectJAutoProxyCreator扫描@AspectJ转换为Advisor的过程。
它将扫描AspectJ和创建对应Advisor的过程委托给了 BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder
1 | /** |
下面看看 ReflectiveAspectJAdvisorFactory.getAdvisors具体扫描 @AspectJ 创建 Advisor 的过程。
1 | // 根据 AspectJ 注解的类,构建 Advisor |
最后看看Advisor是否适合当前bean 的过程,具体是AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply,实际执行的是 AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass):
1 | // 这里对于 IntroductionAdvisor 的处理是不同的,是单独处理的 |
到这里 整个准备工作就完成了。最后还有几个小点要说:
优先级问题:
AspectJPrecedenceInformation 接口是专门针对于基于@AspectJ注解中,产生的Advisor, Advice无法判断优先级的问题的。
Advisor的排序是先根据自身的Order,如果没有设置Order,就从Advice中拿,如果还没有 就是最低:
1 | // AbstractPointcutAdvisor |
Advice的排序也是根据Order的,但是对于AspectJ注解产生的Advice,他们的Order都是一样的,所以通过AspectJPrecedenceInformation 来保存元数据信息,并根据 @Arount,@Before, @After, ..注解的顺序先排序,再根据方法的名字再排序,最后的结果作为advice 的顺序。具体可以看 ReflectiveAspectJAdvisorFactory.METHOD_COMPARATOR
AspectJ 再单独说明
本源码分析流程就是以@AspectJ为例跑的。另外也比较特殊,可以专门再说一下。
Advisor是class InstantiationModelAwarePointcutAdvisorImpl implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, SerializableAdvice是public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable它具体的实现类有AspectJAfterAdvice等Pointcut是public class AspectJExpressionPointcut extends AbstractExpressionPointcut implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware。 他的父类AbstractExpressionPointcut就是多定义了 几个属性expression, location等,具体逻辑 还是在这个类中AspectJExpressionPointcut中的ClassFilter 和 MethodMatcher 都是 根据 expression 也就是@Before类似这种注解的value来生成的。 具体某个类到底通不通过 filter,matches 其实是交给 AspectJ 处理的。包括 “@annotation “这种express
1 |
|
其他接口
上文还有一些接口类没说到,但是也挺重要的,虽然用的不多,这里再说一下:
AspectJPrecedenceInformationAspectJ 的其他基本信息,主要用于排序IntroductionAdvisorAdvisor 的另一类,一般都是PointcutAdvisor。 在判断Advisor 是否AopUtils.canApply的时候,会优先处理IntroductionAdvisor,而且PointcutAdvisor是否canApply,还会受到IntroductionAdvisor结果的影响。但是它用的并不多,自己也没有细研究。IntroductionAwareMethodMatcher如果想要影响PointcutAdvisor,需要配合该类使用,只有PointcutAdvisor中的Pointcut是该类型的,才有可能收到影响,因为是该类型的,才在他的MethodMatcher.matches中加上IntroductionAdvisorcanApply的结果。
- 还有各种Spring提供的Advisor(
正则Advisor,NameMatcherAdvisor,DefaultAdvisor),提供的ProxyCreator(AbstractAdvisorProxyCreator的子类),提供好的Pointcut(JDK正则Pointcut,NameMatchPointcut等) AdvisorAdapterRegistry可以保证,注入的advisor 可以是任何类型,只要我们再自定义个 Adapter 去包装下就行了。实际使用的是DefaultAdvisorAdapterRegistry
创建与执行代理-Proxy
在AbstractAutoProxyCreator.wrapIfNecessary中,获取了Advisor,并创建了代理。
AnnotationAwareAspectJAutoProxyCreator实现类会添加一个通用的AdvisorExposeInvocationInterceptor,作用是在执行的时候将当前的MethodInvocation保存在ThreadLocal中。具体细节就不看了。。
真正创建代理的方法是拿到 Object[] specificInterceptors,也就是通常使用的Advisor数组后,执行的:
1 | // AbstractAutoProxyCreator.wrapIfNecessary |
下面仔细分析下流程:
1 | protected Object createProxy(Class<?> beanClass, @Nullable String beanName, |
具体看看怎么 buildAdvisors:
1 | protected Advisor[] buildAdvisors( String beanName, Object[] specificInterceptors) { |
ProxyFactory 的 proxyFactory.getProxy(getProxyClassLoader()); 具体是怎么创建的:
1 |
|
说在最后
AspectJ是AOP的一种实现方式,而且拆分的特别细,采用的execute 等这一套东西。
SpringAOP是Spring中非常核心的一个东西,就像Context或者BeanFactory一样,是spring的构成基础。
SpringAOP提供了一套非常完整而且方便灵活的体系,通过Advice定义代理的逻辑,Pointcut定义代理的目标扫描对象,并用Advisor将这两个灵活组合,可以任意搞代理。
ApsectJ和execute 中的一套东西,包括@Before @After等等,SpringAOP为了兼容AspectJ 专门提供了一套Advice、Pointcut、Advisor来满足适配这些。
其实以后为了方便,完全不需要用AspectJ这一套扫描方案,明明自定义的Pointcut和Advice才是最方便灵活的。