5.Spring AOP自动代理(二)筛选合适的通知器
5.Spring AOP自动代理(二)筛选合适的通知器
Spring 版本:5.1.14.RELEASE
在上一篇《Spring AOP 自动代理(一)入口》文章中,分析了 Spring AOP 自动代理的入口是 AbstractAutoProxyCreator 对象,其中自动代理的过程主要分为下面两步:
1、 筛选出能够应用于当前Bean的Advisor;
2、 找到了合适Advisor则创建一个代理对象,JDK动态代理或者CGLIB动态代理;
本文就接着上篇文章来分析筛选合适的通知器的处理过程,包含 @AspectJ
等 AspectJ
注解的解析过程。这里的“通知器”指的是 Advisor 对象。
回顾
// AbstractAutoProxyCreator.java
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
/*
* <1> 如果当前 Bean 已经创建过自定义 TargetSource 对象
* 表示在上面的**实例化前置处理**中已经创建代理对象,那么直接返回这个对象
*/
if (StringUtils.hasLength(beanName)
&& this.targetSourcedBeans.contains(beanName))
{
return bean;
}
// `<2>` advisedBeans 保存了这个 Bean 没有必要创建代理对象,则直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/*
* <3> 不需要创建代理对象,则直接返回当前 Bean
*/
if (isInfrastructureClass(bean.getClass()) // 如果是 Spring 内部的 Bean(Advice、Pointcut、Advisor 或者 AopInfrastructureBean 标记接口)
|| shouldSkip(bean.getClass(), beanName)) // 应该跳过
{
// 将这个 Bean 不需要创建代理对象的结果保存起来
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// <4> 获取能够应用到当前 Bean 的所有 Advisor(已根据 @Order 排序)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// <5> 如果有 Advisor,则进行下面的动态代理创建过程
if (specificInterceptors != DO_NOT_PROXY) {
// `<5.1>` 将这个 Bean 已创建代理对象的结果保存至 advisedBeans
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// <5.2> 创建代理对象,JDK 动态代理或者 CGLIB 动态代理
// 这里传入的是 SingletonTargetSource 对象,可获取代理对象的目标对象(当前 Bean)
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// <5.3> 将代理对象的 Class 对象(目标类的子类)保存
this.proxyTypes.put(cacheKey, proxy.getClass());
// <5.4> 返回代理对象
return proxy;
}
// <6> 否则,将这个 Bean 不需要创建代理对象的结果保存起来
this.advisedBeans.put(cacheKey, Boolean.FALSE);
// <7> 返回这个 Bean 对象
return bean;
}
在创建代理对象的过程中,上面方法的第 4
步调用 getAdvicesAndAdvisorsForBean(..)
方法,获取能够应用到当前 Bean 的所有 Advisor(已根据 @Order 排序)
// AbstractAutoProxyCreator.java
protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
@Nullable TargetSource customTargetSource) throws BeansException;
抽象方法,交由子类实现
筛选出合适的 Advisor 的流程
1、 解析出当前IoC容器所有Advisor对象;
1、 获取当前IoC容器所有Advisor类型的Bean;
2、 解析当前IoC容器中所有带有@AspectJ
注解的Bean,将内部带有@Before|@After|@Around|@AfterReturning|@AfterThrowing
注解的方法解析出对应的PointcutAdvisor对象,带有@DeclareParents
注解的字段解析出IntroductionAdvisor对象;
`@Around` \-> AspectJAroundAdvice,实现了 MethodInterceptor
`@Before` \-> AspectJMethodBeforeAdvice
`@After` \-> AspectJAfterAdvice,实现了 MethodInterceptor
`@AfterReturning` \-> AspectJAfterAdvice
`@AfterThrowing` \-> AspectJAfterThrowingAdvice,实现了 MethodInterceptor
2、 筛选出能够应用于这个Bean的Advisor们,主要通过ClassFilter类过滤器和MethodMatcher方法匹配器进行匹配;
3、 对筛选出来的Advisor进行扩展,例如子类会往首部添加一个PointcutAdvisor对象;
4、 对筛选出来的Advisor进行排序;
- 不同的 AspectJ 根据
@Order
排序 - 同一个 AspectJ 中不同 Advisor 的排序,优先级:
AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice
主要涉及到下面几个类:
- AbstractAdvisorAutoProxyCreator:支持从当前 Spring 上下文获取所有 Advisor 对象
- AnnotationAwareAspectJAutoProxyCreator:支持从带有 @AspectJ 注解 Bean 中解析 Advisor 对象
- BeanFactoryAspectJAdvisorsBuilder:Advisor 构建器,用于解析出当前 BeanFactory 中所有带有 @AspectJ 注解的 Bean 中的 Advisor
- ReflectiveAspectJAdvisorFactory:Advisor 工厂,用于解析 @AspectJ 注解的 Bean 中的 Advisor
AnnotationAwareAspectJAutoProxyCreator 继承 AbstractAdvisorAutoProxyCreator,借助 BeanFactoryAspectJAdvisorsBuilder 构建器,这个构建器又借助 ReflectiveAspectJAdvisorFactory 工厂。
AbstractAdvisorAutoProxyCreator
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
:支持从当前 Spring 上下文获取所有 Advisor 对象,存在能应用与 Bean 的 Advisor 则创建代理对象
构造函数
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
/** Advisor 检索工具类 */
@Nullable
private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException(
"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
}
// 初始化工作
initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 设置 Advisor 检索工具类为 BeanFactoryAdvisorRetrievalHelperAdapter
this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}
}
1. getAdvicesAndAdvisorsForBean 方法
getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource)
,筛选某个 Bean 合适的 Advisor,如下:
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
// 获取能够应用到当前 Bean 的所有 Advisor(已根据 @Order 排序)
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
// 转换成数组并返回
return advisors.toArray();
}
调用findEligibleAdvisors(Class<?> beanClass, String beanName)
方法,获取能够应用到当前 Bean 的所有 Advisor(已根据 @Order 排序)
2. findEligibleAdvisors 方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
/*
* <1> 解析出当前 IoC 容器所有的 Advisor 对象
* 1. 本身是 Advisor 类型的 Bean,默认情况下都会
* 2. 从带有 @AspectJ 注解的 Bean 中解析出来的 Advisor,子类 AnnotationAwareAspectJAutoProxyCreator 会扫描并解析
* PointcutAdvisor:带有 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解的方法
* 其中 Pointcut 为 AspectJExpressionPointcut,Advice 就是注解标注的方法
* IntroductionAdvisor:带有 @DeclareParents 注解的字段
*
* 未排序,获取到的 Advisor 在同一个 AspectJ 中的顺序是根据注解来的,@Around > @Before > @After > @AfterReturning > @AfterThrowing
*/
List<Advisor> candidateAdvisors = findCandidateAdvisors();
/*
* `<2>` 筛选出能够应用到 beanClass 上面的所有 Advisor 对象并返回
* 也就是通过 ClassFilter 进行匹配,然后再通过 MethodMatcher 对所有方法进行匹配(有一个即可)
* AspectJExpressionPointcut 就实现了 ClassFilter 和 MethodMatcher
*/
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
/*
* <3> 抽象方法,交由子类拓展
* 例如 AspectJAwareAdvisorAutoProxyCreator 的实现
* 如果 eligibleAdvisors 中存在和 AspectJ 相关的 Advisor
* 则会在 eligibleAdvisors 首部添加一个 DefaultPointcutAdvisor 对象,对应的 Advice 为 ExposeInvocationInterceptor 对象
* 用于暴露 MethodInvocation 对象(Joinpoint 对象),存储在 ThreadLocal 中,在其他地方则可以使用
*/
extendAdvisors(eligibleAdvisors);
// `<4>` 对 eligibleAdvisors 集合进行排序,根据 @Order 注解进行排序
if (!eligibleAdvisors.isEmpty()) {
// 不同的 AspectJ 根据 @Order 排序
// 同一个 AspectJ 中不同 Advisor 的排序:AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
// <5> 返回排序后的能够应用到当前 Bean 的所有 Advisor
return eligibleAdvisors;
}
该方法的处理过程如下:
1、 调用findCandidateAdvisors()
方法,解析出当前IoC容器所有的Advisor对象,得到candidateAdvisors
集合,来源:;
本身是 Advisor 类型的 Bean,默认情况下都会
从带有
@AspectJ
注解的 Bean 中解析出来的 Advisor
2、 调用findAdvisorsThatCanApply(..)
方法,筛选出能够应用到beanClass
上面的所有Advisor对象并返回,得到eligibleAdvisors
集合;通过 ClassFilter 进行匹配,然后再通过 MethodMatcher 对所有方法进行匹配(有一个即可)
3、 调用extendAdvisors(List<Advisor>candidateAdvisors)
方法,对eligibleAdvisors
进行处理;
4、 调用sortAdvisors(List<Advisor>advisors)
方法,对eligibleAdvisors
进行排序;
5、 返回排序后的能够应用到当前Bean的所有Advisor;
接下来依次对上面的方法进行分析
2.1.1 findCandidateAdvisors 方法
findCandidateAdvisors()
,该方法会去找符合条件的 Advisor 们,AbstractAdvisorAutoProxyCreator 的实现则是去找当前 IoC 容器中所有 Advisor 类型的 Bean,如下:
// AbstractAdvisorAutoProxyCreator.java
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
// 借助 BeanFactoryAdvisorRetrievalHelperAdapter 从 IoC 容器中查找所有的 Advisor 对象
return this.advisorRetrievalHelper.findAdvisorBeans();
}
可以看到是借助于 BeanFactoryAdvisorRetrievalHelperAdapter 去找 Advisor 类型的 Bean,如下:
// BeanFactoryAdvisorRetrievalHelperAdapter.java
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
// <1> 先从缓存中获取所有 Advisor
String[] advisorNames = this.cachedAdvisorBeanNames;
// <2> 没有缓存
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
// <2.1> 从当前 BeanFactory 容器中找到所有 Advisor 类型的 bean 的名称
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
// <2.2> 放入缓存中
this.cachedAdvisorBeanNames = advisorNames;
}
// <3> 如果没有 Advisor,则返回一个空集合
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
/*
* <4> 遍历所有的 Advisor 类型的 Bean 的名称,获取对应的 Bean
*/
for (String name : advisorNames) {
// <4.1> 判断这个 Bean 是否有资格,默认为 true
if (isEligibleBean(name)) {
// <4.2> 正在初始化,则先跳过
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
// <4.3> 否则,获取对应的 Bean
else {
try {
// 依赖查找到这个 Advisor 对象
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
// ...
throw ex;
}
}
}
}
// <5> 返回 IoC 容器中所有的 Advisor
return advisors;
}
该方法的处理过程如下:
1、 先从缓存中获取所有Advisor;
2、 没有缓存;
1、 从当前BeanFactory容器中找到所有Advisor类型的Bean的名称;
2、 放入缓存中;
3、 如果没有Advisor,则返回一个空集合;
4、 遍历所有的Advisor类型的Bean的名称,获取对应的Bean;
1、 判断这个Bean是否有资格,默认为true
;
2、 正在初始化,则先跳过;
3、 否则,获取对应的Bean,依赖查找到这个Advisor对象;
5、 返回IoC容器中所有的Advisor;
总结下来,就是从当前 Spring IoC 容器中找到所有 Advisor 类型的 Bean
2.2 findAdvisorsThatCanApply 方法
findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName)
方法,从 candidateAdvisors
中找到能够应用于 beanClass
的 Advisor,如下:
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
/*
* 筛选出能够应用到 beanClass 上面的所有 Advisor 对象并返回
* 也就是通过 ClassFilter 进行匹配,然后再通过 MethodMatcher 对所有方法进行匹配(有一个即可)
* AspectJExpressionPointcut 就实现了 ClassFilter 和 MethodMatcher
*/
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
可以看到是借助于 AopUtils 工具类从 candidateAdvisors
中找到能够应用于 beanClass
的 Advisor,如下:
// AopUtils.java
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
/*
* <1> 遍历所有的 Advisor 对象
* 找到能够应用当前 Bean 的 IntroductionAdvisor 对象,放入 eligibleAdvisors 集合中
*/
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor // 如果是 IntroductionAdvisor 类型
&& canApply(candidate, clazz)) // 且能够应用到当前 Bean 中,通过其 ClassFilter 进行过滤
{
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
/*
* <2> 遍历所有的 Advisor 对象
* 如果是 IntroductionAdvisor 类型,则会跳过,因为上面已经判断过
* 找到能够应用当前 Bean 的 Advisor 对象,放入 eligibleAdvisors 集合中
*/
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
// 判断是否能够应用到这个 Bean 上面
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
// <3> 返回能够应用到当前 Bean 的所有 Advisor 对象
return eligibleAdvisors;
}
该方法的处理过程如下:
1、 遍历所有的Advisor对象,找到能够应用当前Bean的IntroductionAdvisor
对象,放入eligibleAdvisors
集合中,需要满足下面两个条件;
- 是
IntroductionAdvisor
类型 - 能够应用到当前 Bean 中,通过其 ClassFilter 进行过滤
2、 遍历所有的Advisor对象,找到能够应用当前Bean的Advisor对象,放入eligibleAdvisors
集合中;如果是IntroductionAdvisor
类型,则会跳过,因为上面已经判断过;
3、 返回能够应用到当前Bean的所有Advisor对象;
AopUtils#canApply 方法
如何判断这个 Advisor 能够应用于某个 Bean 都是调用 canApply(..)
方法如下:
// AopUtils.java
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
/*
* 从 IntroductionAdvisor 中获取 ClassFilter 类过滤器,判断这个目标类是否符合条件
*/
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
/*
* 根据 Pointcut 中的 ClassFilter 和 MethodFilter 进行过滤
* 例如 Aspect 的实现类 AspectJExpressionPointcut
*/
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
// 否则,没有 Pointcut,也就是没有筛选条件,则都符合条件
return true;
}
}
如果IntroductionAdvisor
类型的 Advisor 则通过 ClassFilter 类过滤器进行判断即可;如果是 PointcutAdvisor
类型的 Advisor 则需要调用 canApply(..)
的重载方法进行判断;否则,没有 Pointcut,也就是没有筛选条件,则都符合条件
AopUtils#canApply 重载方法
如何判断 PointcutAdvisor
类型的 Advisor 能够应用于某个 Bean 的过程如下:
// AopUtils.java
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
// `<1>` 使用 ClassFilter 匹配 targetClass
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
// <2> 获取 MethodMatcher 方法匹配器
MethodMatcher methodMatcher = pc.getMethodMatcher();
// <3> 如果方法匹配器为 TrueMethodMatcher,则默认都通过
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
// <4> 如果方法匹配器为 IntroductionAwareMethodMatcher,则进行转换
// AspectJExpressionPointcut 就是 IntroductionAwareMethodMatcher 的实现类
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
/*
* `<5>` 获取目标类、以及实现的所有接口,并添加至 classes 集合中
*/
Set<Class<?>> classes = new LinkedHashSet<>();
// <5.1> 如果不是 java.lang.reflect.Proxy 的子类
if (!Proxy.isProxyClass(targetClass)) {
// 获取目标类的 Class 对象(如果目标类是 CGLIB 代理对象,则获取其父类的 Class 对象,也就得到了目标类)
classes.add(ClassUtils.getUserClass(targetClass));
}
// <5.2> 获取目标类实现的所有接口,如果目标类本身是一个接口,那么就取这个目标类
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
/*
* `<6>` 遍历上面的 classes 集合
*/
for (Class<?> clazz : classes) {
// <6.1> 获取这个 Class 对象的所有方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
// <6.2> 遍历上一步获取到的所有方法
for (Method method : methods) {
// `<6.3>` 使用方法匹配器对该方法进行匹配,如果匹配成功则直接返回 true
// AspectJExpressionPointcut 底层就是通过 AspectJ 进行处理的
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
// `<7>` 一个方法都没匹配则返回 false,表示这个 Advisor 不能应用到这个 Bean 上面
return false;
}
该方法的处理过程如下:
1、 使用Pointcut的ClassFilter匹配targetClass
,不通过则直接返回false
;
2、 获取Pointcut的MethodMatcher方法匹配器,保存至methodMatcher
;
3、 如果methodMatcher
为TrueMethodMatcher,则默认都通过,返回true
;
4、 如果methodMatcher
为IntroductionAwareMethodMatcher,则进行转换,保存至introductionAwareMethodMatcher
;
- AspectJExpressionPointcut 就是 IntroductionAwareMethodMatcher 的实现类
5、 获取目标类、以及实现的所有接口,并添加至classes
集合中;
1、 如果不是java.lang.reflect.Proxy的子类,则获取targetClass
目标类的Class对象(如果目标类是CGLIB代理对象,则获取其父类的Class对象,也就得到了目标类);
2、 获取targetClass
目标类实现的所有接口,如果目标类本身是一个接口,那么就取这个目标类;
6、 遍历上面的classes
集合;
1、 获取这个Class对象的所有方法;
2、 遍历上一步获取到的所有方法;
3、 使用methodMatcher
方法匹配器对该方法进行匹配,优先使用introductionAwareMethodMatcher
方法匹配器,匹配成功则直接返回true
,说明有一个方法满足条件即可;
* AspectJExpressionPointcut 底层就是通过 AspectJ 的表达式处理进行处理的
7、 一个方法都没匹配成功则返回false
,表示这个Advisor不能应用到这个Bean上面;
总结下来,PointcutAdvisor 是根据 Pointcut 的 ClassFilter 对目标类进行过滤,如果通过的话,则通过 MethodMatcher 方法匹配器对目标类的方法进行匹配,有一个方法满足条件就表示这个 PointcutAdvisor 可以应用于目标类
2.3 extendAdvisors 方法
extendAdvisors(List<Advisor> candidateAdvisors)
放,对筛选出来的 Advisor 进行扩展,抽象方法,我们来看到子类的实现:
// AspectJAwareAdvisorAutoProxyCreator.java
@Override
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
可以看到是借助于 AspectJProxyUtils 工具类进行扩展,如下:
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
// 遍历所有 Advisor
for (Advisor advisor : advisors) {
// Be careful not to get the Advice without a guard, as this might eagerly
// instantiate a non-singleton AspectJ aspect...
// 判断这个 Advisor 是否和 AspectJ 相关
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
break;
}
}
// 如果 advisors 涉及到和 AspectJ 相关的 Advisor
// 则向其首部添加一个 DefaultPointcutAdvisor 对象,对应的 Advice 为 ExposeInvocationInterceptor 对象
// 用于暴露 MethodInvocation 对象(Joinpoint 对象),存储在 ThreadLocal 中,在其他地方则可以使用
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
private static boolean isAspectJAdvice(Advisor advisor) {
return ( advisor instanceof InstantiationModelAwarePointcutAdvisor
|| advisor.getAdvice() instanceof AbstractAspectJAdvice
|| ( advisor instanceof PointcutAdvisor && ((PointcutAdvisor) advisor).getPointcut() instanceof AspectJExpressionPointcut) );
}
处理过程很简单,当存在和 AspectJ 相关的 Advisor(使用了 AspectJ 的注解这里都是 true
),则在首部添加一个 DefaultPointcutAdvisor 对象
添加的这个 Advisor 对应的 Advice 为 ExposeInvocationInterceptor 方法拦截器,用于暴露 MethodInvocation 对象(Joinpoint 对象),存储在 ThreadLocal 中,在其他地方则可以使用
2.4 sortAdvisors 方法
sortAdvisors(List<Advisor> advisors)
方法,对筛选出来的 Advisor 进行排序,如下:
// AspectJAwareAdvisorAutoProxyCreator.java
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
for (Advisor element : advisors) {
// 使用 AspectJPrecedenceComparator 比较器
partiallyComparableAdvisors.add(
new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
}
List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
if (sorted != null) {
List<Advisor> result = new ArrayList<>(advisors.size());
for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
result.add(pcAdvisor.getAdvisor());
}
return result;
}
else {
// AbstractAdvisorAutoProxyCreator
// 使用 AnnotationAwareOrderComparator 比较器,通过 @Order 注解
return super.sortAdvisors(advisors);
}
}
AspectJPrecedenceComparator 是对 AnnotationAwareOrderComparator 的包装,进行了扩展,排序不同类型的 Advice,详细的过程这里不展述了
我通过Debug 打断点得到的结论:
- 不同的 AspectJ 根据 @Order 排序
- 同一个 AspectJ 中不同 Advisor 的排序,优先级如下:
AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice
小结
到这里我们可以一个结论,筛选合适的通知器的总的过程在 AbstractAdvisorAutoProxyCreator#findEligibleAdvisors(..) 方法中进行,分为下面几步:
1、 找符合条件的Advisor们,在AbstractAdvisorAutoProxyCreator则是去找当前IoC容器中所有Advisor类型的Bean;
2、 从上一步找到的Advisor筛选出能够应用于当前Bean的Advisor们,主要是通过Pointcut的ClassFilter类过滤器和MethodMatcher方法匹配器进行判断,有一个方法匹配这个Advisor即满足条件;
3、 支持对找到的Advisor集合进行扩展,在子类中会往其首部添加一个方法拦截器为ExposeInvocationInterceptor的PointcutAdvisor;
4、 对找到的合适的Advisor进行排序,排序结果如上所述;
上面过程的第 1
步仅找到当前 IoC 容器中所有 Advisor 类型的 Bean,是不是没有对 AspectJ 相关注解进行解析,这个过程在子类中实现,也就是接下来要讲的内容
AnnotationAwareAspectJAutoProxyCreator
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
:支持从带有 @AspectJ
注解 Bean 中解析 Advisor 对象
构造函数
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
/**
* 用于指定哪些 Bean 能够作为 Advisor
*/
@Nullable
private List<Pattern> includePatterns;
/**
* 解析 AspectJ 注解的 Advisor 工厂
*/
@Nullable
private AspectJAdvisorFactory aspectJAdvisorFactory;
/**
* 构建器模式,用于构建 AspectJ 注解的 Advisor
*/
@Nullable
private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 初始化 BeanFactoryAdvisorRetrievalHelperAdapter
super.initBeanFactory(beanFactory);
// 初始化 ReflectiveAspectJAdvisorFactory
if (this.aspectJAdvisorFactory == null) {
this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
}
// 初始化 BeanFactoryAspectJAdvisorsBuilderAdapter
this.aspectJAdvisorsBuilder =
new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
}
2.1.2 findCandidateAdvisors 方法
findCandidateAdvisors()
,该方法会去找符合条件的 Advisor 们,通过父类找到当前 IoC 容器中所有 Advisor 类型的 Bean,这里又会解析出带有 @AspectJ
注解的 Bean 中的 Advisor 们,如下:
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// <1> 调用父类方法,从 IoC 容器中查找所有的 Advisor 类型的 Bean
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
// <2> 如果 AspectJ 解析器不为空,默认为 BeanFactoryAspectJAdvisorsBuilderAdapter
if (this.aspectJAdvisorsBuilder != null) {
// 解析所有带有 @AspectJ 注解的 Bean
// 其中带有 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解的方法会被解析成一个 PointcutAdvisor 对象
// 将解析出来的所有 Advisor 添加至 advisors 中
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
// `<3>` 返回 advisors 集合(当前 IoC 容器中解析出来的所有的 Advisor 对象)
return advisors;
}
该方法的处理过程如下:
1、 调用父类方法,从IoC容器中查找所有的Advisor类型的Bean,保存至advisors
中,可返回上面的2.1.1findCandidateAdvisors方法
小节查看;
2、 如果AspectJ解析器不为空,默认为BeanFactoryAspectJAdvisorsBuilderAdapter,则通过它解析出Advisor来;
- 解析所有带有
@AspectJ
注解的 Bean - 其中带有
@Before|@After|@Around|@AfterReturning|@AfterThrowing
注解的方法会被解析成一个 PointcutAdvisor 对象 - 将解析出来的所有 Advisor 添加至
advisors
中
3、 返回advisors
集合(当前IoC容器中解析出来的所有的Advisor对象);
BeanFactoryAspectJAdvisorsBuilderAdapter
关于@AspectJ
注解的解析由 BeanFactoryAspectJAdvisorsBuilderAdapter 完成,如下:
// AnnotationAwareAspectJAutoProxyCreator.java
private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {
public BeanFactoryAspectJAdvisorsBuilderAdapter(
ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
super(beanFactory, advisorFactory);
}
@Override
protected boolean isEligibleBean(String beanName) {
return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
}
}
protected boolean isEligibleAspectBean(String beanName) {
if (this.includePatterns == null) {
return true;
} else {
for (Pattern pattern : this.includePatterns) {
if (pattern.matcher(beanName).matches()) {
return true;
}
}
return false;
}
}
这里只重写了 isEligibleBean(String)
方法,用于判断这个 Bean 是否有资格作为一个 Advisor。可以看到是通过 includePatterns
对 beanName
进行判断,匹配通过才有资格。当然,includePatterns
一般为空,都有资格。
这个类继承了 BeanFactoryAspectJAdvisorsBuilder 构建器,我们来看到这个构建器是如何解析的。
BeanFactoryAspectJAdvisorsBuilder
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder
,Advisor 构建器,用于解析出当前 BeanFactory 中所有带有 @AspectJ
注解的 Bean 中的 Advisor
构造函数
public class BeanFactoryAspectJAdvisorsBuilder {
/**
* 当前 IoC 容器,DefaultListableBeanFactory
*/
private final ListableBeanFactory beanFactory;
/**
* Advisor 工厂,用于解析 @AspectJ 注解的 Bean 中的 Advisor
*/
private final AspectJAdvisorFactory advisorFactory;
/**
* 用于缓存带有 @AspectJ 注解的 Bean 的名称
*/
@Nullable
private volatile List<String> aspectBeanNames;
/**
* 缓存 @AspectJ 注解的单例 Bean 中解析出来的 Advisor
* key:带有 @AspectJ 注解的 beanName
* value:其内部解析出来的 Advisor 集合
*/
private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>();
/**
* 缓存 @AspectJ 注解的非单例 Bean 的元数据实例构建工厂
* key:带有 @AspectJ 注解的 beanName(非单例)
* value:对应的元数据工厂对象
*/
private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache = new ConcurrentHashMap<>();
public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
Assert.notNull(beanFactory, "ListableBeanFactory must not be null");
Assert.notNull(advisorFactory, "AspectJAdvisorFactory must not be null");
this.beanFactory = beanFactory;
this.advisorFactory = advisorFactory;
}
}
2.1.3 buildAspectJAdvisors 方法
buildAspectJAdvisors()
方法,解析出当前 BeanFactory 中所有带有 @AspectJ
注解的 Bean 中的 Advisor,如下:
public List<Advisor> buildAspectJAdvisors() {
// `<1>` 从缓存中获取所有带有 @AspectJ 注解的 Bean,保存至 aspectNames 集合中
List<String> aspectNames = this.aspectBeanNames;
// <2> 缓存中没有,则对当前对象加锁再判断缓存中是否有数据
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
// <3> 还是没有缓存,则进行接下来的处理
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
// <3.1> 获取当前 IoC 容器中所有的 Bean 的名称集合
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// <3.2> 遍历所有的 Bean 的名称,进行处理
for (String beanName : beanNames) {
// <3.3> 判断这个 Bean 是否有资格,默认都为 true
if (!isEligibleBean(beanName)) {
// 如果没有资格则跳过
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
// <3.4> 获取这个 Bean 的 Class 对象,如果为空则跳过
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// `<3.5>` 如果这个 Bean 带有 @Aspect 注解,且没有以 ajc$ 开头的字段,那么进行接下来的解析过程
if (this.advisorFactory.isAspect(beanType)) {
// `<3.5.1>` 将这个 Bean 的名称保存至 aspectNames 集合中
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
// `<3.5.2>` 判断 @AspectJ 注解的类别是否为 singleton,默认空的情况就是这个
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
// <3.5.2.1> 解析这个 Bean 中带有 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解的方法
// 会解析成对应的 InstantiationModelAwarePointcutAdvisorImpl 对象(PointcutAdvisor)
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
// `<3.5.2.2>` 如果这个 Bean 是单例模式,则将解析出来的 Advisor 全部缓存至 advisorsCache 中
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
// `<3.5.2.3>` 否则,将这个 Bean 对应的 MetadataAwareAspectInstanceFactory(AspectJ 元数据实例构建工厂)缓存至 aspectFactoryCache 中
else {
this.aspectFactoryCache.put(beanName, factory);
}
// `<3.5.2.4>` 将解析出来的 Advisor 添加至 advisors 中
advisors.addAll(classAdvisors);
}
// <3.5.3> 否则,这个 AspectJ 不是单例模式,不能将解析出来的 Advisor 缓存,其他的处理过程都和上面一样
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
// 将这个 Bean 对应的 MetadataAwareAspectInstanceFactory(AspectJ 元数据实例构建工厂)缓存至 aspectFactoryCache 中
this.aspectFactoryCache.put(beanName, factory);
// 解析出这个 Bean 中所有的 Advisor,并添加至 advisors 中
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
// `<3.6>` 对 aspectNames 进行缓存
this.aspectBeanNames = aspectNames;
// <3.7> 返回所有 AspectJ 的所有的 Advisor 对象们
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
/*
* <4> 否则,遍历缓存中的 AspectJ 的 beanName
*/
for (String aspectName : aspectNames) {
// `<4.1>` 尝试从 advisorsCache 缓存中获取这个 beanName 对应的所有 Advisor 们,并添加至 advisors 中
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
// `<4.2>` advisorsCache 缓存中没有,
// 则根据 aspectFactoryCache 缓存中对应的 MetadataAwareAspectInstanceFactory(AspectJ 元数据实例构建工厂)解析出所有的 Advisor 们,并添加至 advisors 中
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
// <5> 返回所有 AspectJ 的所有的 Advisor 对象们
return advisors;
}
该方法的处理过程稍微有点复杂,如下:
1、 从缓存中获取所有带有@AspectJ
注解的Bean,保存至aspectNames
集合中;
2、 缓存中没有,则对当前对象加锁再判断缓存中是否有数据;
3、 还是没有缓存,则进行接下来的处理;
1、 获取当前IoC容器中所有的Bean的名称集合;
2、 遍历所有的Bean的名称,进行处理;
3、 判断这个Bean是否有资格,默认都为true
;
4、 获取这个Bean的Class对象,如果为空则跳过;
5、 如果这个Bean带有@Aspect
注解,且没有以ajc$
开头的字段,那么进行接下来的解析过程;
1. 将这个 Bean 的名称保存至 `aspectNames` 集合中
2. 判断 `@AspectJ` 注解的类别是否为 `singleton`,默认空的情况就是这个
1. 通过 AspectJAdvisorFactory#getAdvisors(..) 方法解析出这个 Bean 中带有 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解的方法,例如会解析成 InstantiationModelAwarePointcutAdvisorImpl 对象(PointcutAdvisor)
2. 如果这个 Bean 是单例模式,则将解析出来的 Advisor 全部缓存至 `advisorsCache` 中
3. 否则,将这个 Bean 对应的 MetadataAwareAspectInstanceFactory(AspectJ 元数据实例构建工厂)缓存至 `aspectFactoryCache` 中
4. 将解析出来的 Advisor 添加至 `advisors` 中
3. 否则,这个 AspectJ 不是**单例模式**,不能将解析出来的 Advisor 缓存,其他的处理过程都和上面一样
6、 对aspectNames
进行缓存;
7、 返回所有AspectJ的所有的Advisor对象们;
4、 否则,遍历缓存中的AspectJ的beanName
,进行处理;
1、 尝试从advisorsCache
缓存中获取这个beanName
对应的所有Advisor们,并添加至advisors
中;
2、 advisorsCache
缓存中没有,则根据aspectFactoryCache
缓存中对应的MetadataAwareAspectInstanceFactory(AspectJ元数据实例构建工厂)解析出所有的Advisor们,并添加至advisors
中;
5、 返回所有AspectJ的所有的Advisor对象们;
做个小结,整个过程稍微复杂一点,会尝试从缓存中获取 Advisor,缓存中没有数据则先获取到所有带有 @AspectJ
注解的 Bean,通过 ReflectiveAspectJAdvisorFactory 对这些 Bean 中带有 AspectJ 相关注解的方法进行处理,生成对应的 PointcutAdvisor 对象。
接下来,我们来看看 ReflectiveAspectJAdvisorFactory 解析 @AspectJ
注解的 Bean 的过程
ReflectiveAspectJAdvisorFactory
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory
,Advisor 工厂,用于解析 @AspectJ
注解的 Bean 中的 Advisor
构造函数
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
/**
* 方法比较器
*/
private static final Comparator<Method> METHOD_COMPARATOR;
static {
Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
new InstanceComparator<>( Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
(Converter<Method, Annotation>) method -> {
AspectJAnnotation<?> annotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
return (annotation != null ? annotation.getAnnotation() : null);
});
Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
}
}
可以看到有一个 Comparator 方法比较器,顺序是 @Around > @Before > @After > @AfterReturning > @AfterThrowing
,注意获取到应用于某个 Bean 的 Advisor 的顺序不是这样子,可以回到前面的 2.4 sortAdvisors 方法
小节看看
2.1.3.1 getAdvisors 方法
getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory)
方法,解析出这个 Bean(带有 @AspectJ
注解)中所有的 Advisor,方法入参是 Bean 的元数据实例构建工厂,方法如下:
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
// <1> 获取这个 Bean 的 Class 对象和 beanName
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
/*
* <2> 遍历没有标注 @Pointcut 注解的方法(顺序:@Around > @Before > @After > @AfterReturning > @AfterThrowing)
*/
for (Method method : getAdvisorMethods(aspectClass)) {
/*
* <2.1> 如果这个方法带有 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解
* 则根据注解信息创建一个 InstantiationModelAwarePointcutAdvisorImpl 对象
* 这个对象就是 PointcutAdvisor 类型,包含了 Pointcut 和 Advice
*/
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
// `<2.2>` 生成了 PointcutAdvisor 则添加至 advisor 集合中
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
// <3> 如果这个 Aspect 需要延迟初始化,则往首部添加一个 PointcutAdvisor
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
// `<4>` 根据带有 @DeclareParents 注解的字段生成 IntroductionAdvisor 对象,并添加至 advisor 集合中
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
// <5> 返回这个 Aspect 中所有的 Advisor 对象
return advisors;
}
该方法的处理过程如下:
1、 获取这个Bean的Class对象和beanName
;
2、 遍历没有标注@Pointcut
注解的方法(顺序:@Around>@Before>@After>@AfterReturning>@AfterThrowing
);
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new ArrayList<>();
ReflectionUtils.doWithMethods(aspectClass, method -> {
// Exclude pointcuts
// 排除 @Pointcut 注解标注的方法
if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
methods.add(method);
}
});
// 进行排序
methods.sort(METHOD_COMPARATOR);
return methods;
}
1、 调用getAdvisor(..)
方法,将这个方法解析成InstantiationModelAwarePointcutAdvisorImpl对象(PointcutAdvisor),这个方法必须带有@Before|@After|@Around|@AfterReturning|@AfterThrowing
注解;
2、 如果上一步解析出了Advisor对象,则添加至advisor
集合中;
3、 如果这个Aspect需要延迟初始化,则往首部添加一个SyntheticInstantiationAdvisor(PointcutAdvisor),暂时忽略;
4、 调用getDeclareParentsAdvisor(..)
方法,根据带有@DeclareParents
注解的字段生成IntroductionAdvisor对象,并添加至advisor
集合中;
private Advisor getDeclareParentsAdvisor(Field introductionField) {
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
if (declareParents == null) {
return null;
}
if (DeclareParents.class == declareParents.defaultImpl()) {
throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
}
return new DeclareParentsAdvisor(
introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
}
5、 返回这个Aspect中所有的Advisor对象,也就是返回advisor
集合;
可以看到 @AspectJ
注解的 Bean 中的 @Before|@After|@Around|@AfterReturning|@AfterThrowing
注解方法在 getAdvisor(..)
方法中进行
2.1.3.2 getAdvisor 方法
getAdvisor(..)
方法,解析 @Before|@After|@Around|@AfterReturning|@AfterThrowing
注解方法,生成 PointcutAdvisor 对象,如下:
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
/*
* <1> 尝试根据该方法生成一个 AspectJExpressionPointcut 对象
* 根据 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解信息进行创建,没有的话则返回 null
*/
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
/*
* <2> 如果存在上面其中一个注解,则将创建的 AspectJExpressionPointcut 封装成 InstantiationModelAwarePointcutAdvisorImpl 对象
* 也就是封装成了 PointcutAdvisor 对象,会初始化一个 Advice,也就是注解标注的方法
* 那么这个对象中就包含了 Pointcut 和 Advice,就可以判断某个方法是否被拦截,拦截后应该如何处理
*/
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}
该方法的处理过程如下:
1、 调用getPointcut(..)
方法,尝试根据该方法生成一个AspectJExpressionPointcut对象,根据@Before|@After|@Around|@AfterReturning|@AfterThrowing
注解信息进行创建,没有的话则返回null
;
2、 如果存在上面其中一个注解,则将创建的AspectJExpressionPointcut封装成InstantiationModelAwarePointcutAdvisorImpl对象,也就是封装成了PointcutAdvisor对象,会初始化一个Advice,也就是注解标注的方法那么这个对象中就包含了Pointcut和Advice,就可以判断某个方法是否被拦截,拦截后应该如何处理;
getPointcut 方法
getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass)
方法,尝试将方法解析成 AspectJExpressionPointcut 对象,如下:
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
// <1> 找到这个方法的 @Before|@After|@Around|@AfterReturning|@AfterThrowing 注解信息
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// <2> 如果带有上面其中一个注解,则创建一个 AspectJExpressionPointcut 对象
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
// <3> 设置 Pointcut 的表达式
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
// <4> 返回 AspectJExpressionPointcut 对象
return ajexp;
}
该方法的处理过程如下:
1、 找到这个方法的@Before|@After|@Around|@AfterReturning|@AfterThrowing
注解信息;
2、 如果带有上面其中一个注解,则创建一个AspectJExpressionPointcut对象;
3、 设置Pointcut的表达式;
4、 返回AspectJExpressionPointcut对象;
getAdvice 方法
getAdvice(..)
方法,主要根据 AspectJExpressionPointcut 初始化一个 Advice 对象,如下:
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
// 获取 @Pointcut、@Around、@Before、@After、@AfterReturning、@AfterThrowing 注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround: // @Around -> AspectJAroundAdvice
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore: // @Before -> AspectJMethodBeforeAdvice
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter: // @After -> AspectJAfterAdvice
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning: // @AfterReturning -> AspectJAfterAdvice
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing: // @AfterThrowing -> AspectJAfterThrowingAdvice
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrder);
/*
* 获取方法的参数名列表
*/
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
// 设置参数名
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
根据注解的类型创建对应的 Advice 类型,如下:
- @Around:AspectJAroundAdvice,实现了 MethodInterceptor
- @Before:AspectJMethodBeforeAdvice
- @After:AspectJAfterAdvice,实现了 MethodInterceptor
- @AfterReturning: AspectJAfterAdvice
- @AfterThrowing:AspectJAfterThrowingAdvice,实现了 MethodInterceptor
InstantiationModelAwarePointcutAdvisorImpl
org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl
,AspectJ 注解方法解析后的对象,实现了 PointcutAdvisor,包含 Pointcut 和 Advice
final class InstantiationModelAwarePointcutAdvisorImpl
implements InstantiationModelAwarePointcutAdvisor, AspectJPrecedenceInformation, Serializable {
private static final Advice EMPTY_ADVICE = new Advice() {};
private final AspectJExpressionPointcut declaredPointcut;
private final Class<?> declaringClass;
private final String methodName;
private final Class<?>[] parameterTypes;
private transient Method aspectJAdviceMethod;
private final AspectJAdvisorFactory aspectJAdvisorFactory;
private final MetadataAwareAspectInstanceFactory aspectInstanceFactory;
private final int declarationOrder;
private final String aspectName;
private final Pointcut pointcut;
private final boolean lazy;
@Nullable
private Advice instantiatedAdvice;
@Nullable
private Boolean isBeforeAdvice;
@Nullable
private Boolean isAfterAdvice;
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
// AspectJExpressionPointcut 对象
this.declaredPointcut = declaredPointcut;
// Advice 所在的 Class 对象
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
// Advice 对应的方法名称
this.methodName = aspectJAdviceMethod.getName();
// Advice 对应的方法参数类型
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
// Advice 对应的方法对象
this.aspectJAdviceMethod = aspectJAdviceMethod;
// Advisor 工厂,用于解析 @AspectJ 注解的 Bean 中的 Advisor
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
// 元数据实例构建工厂
this.aspectInstanceFactory = aspectInstanceFactory;
// 定义的顺序
this.declarationOrder = declarationOrder;
// Advice 所在 Bean 的名称
this.aspectName = aspectName;
// 如果需要延迟初始化,则不立即初始化 Advice 对象
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
// 否则,初始化 Advice 对象
else {
// A singleton aspect.
// AspectJExpressionPointcut 对象
this.pointcut = this.declaredPointcut;
this.lazy = false;
// 根据 AspectJExpressionPointcut 初始化一个 Advice 对象
// @Around:AspectJAroundAdvice,实现了 MethodInterceptor
// @Before:AspectJMethodBeforeAdvice
// @After:AspectJAfterAdvice,实现了 MethodInterceptor
// @AfterReturning: AspectJAfterAdvice
// @AfterThrowing:AspectJAfterThrowingAdvice,实现了 MethodInterceptor
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
}
总结
在上一篇《Spring AOP 自动代理(一)入口》文章讲述了 Spring AOP 自动代理的入口,主要对 AbstractAutoProxyCreator 这个类进行了分析。本文接着上一篇文章分析了在 Spring AOP 自动代理的的过程中,如何从 Spring 上下文筛选出能够应用于某个 Bean 的 Advisor 们,大致的流程如下:
1、 解析出当前IoC容器所有Advisor对象;
1、 获取当前IoC容器所有Advisor类型的Bean;
2、 解析当前IoC容器中所有带有@AspectJ
注解的Bean,将内部带有@Before|@After|@Around|@AfterReturning|@AfterThrowing
注解的方法解析出对应的PointcutAdvisor对象,带有@DeclareParents
注解的字段解析出IntroductionAdvisor对象;
2、 筛选出能够应用于这个Bean的Advisor们,主要通过ClassFilter类过滤器和MethodMatcher方法匹配器进行匹配;
3、 对筛选出来的Advisor进行扩展,例如子类会往首部添加一个PointcutAdvisor对象;
4、 对筛选出来的Advisor进行排序;
- 不同的 AspectJ 根据
@Order
排序 - 同一个 AspectJ 中不同 Advisor 的排序,优先级:
AspectJAfterThrowingAdvice > AspectJAfterReturningAdvice > AspectJAfterAdvice > AspectJAroundAdvice > AspectJMethodBeforeAdvice
AspectJ 中的注解对应的 Advice 类型如下:
- @Around ->` AspectJAroundAdvice,实现了 MethodInterceptor
- @Before ->` AspectJMethodBeforeAdvice
- @After ->` AspectJAfterAdvice,实现了 MethodInterceptor
- @AfterReturning ->` AspectJAfterAdvice
- @AfterThrowing ->` AspectJAfterThrowingAdvice,实现了 MethodInterceptor
好了,本篇文章就到这里了,如果获取到能够应用于某个 Bean 的 Advisor,那么接下来要做的就是为这个 Bean 创建一个代理对象,通过 JDK 动态代理或者 CGLIB 动态代理,将在下篇文章进行分析。
版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: