总结摘要
Spring AOP Aspect 源码02
根据 AOP 配置包装 bean
标准创建流程
源码摘录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| // org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 构建缓存
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 如果缓存中已存在,则表示已进行提前代理,此处跳过代理。
// 详情参见循环依赖相关篇章。
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// AOP 代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
|
主流程
1
2
3
4
5
6
7
| // 入口方法
--> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
--> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
--> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
--> org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization 继承父类 postProcessAfterInitialization 方法。
--|> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
--|> Bean 创建扩展点方法
|
1
2
3
4
5
6
7
8
9
| // org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#postProcessAfterInitialization 继承父类 postProcessAfterInitialization 方法。
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
--> 获取缓存 key。
--|> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getCacheKey
--> `this.earlyProxyReferences.remove(cacheKey) != bean`
--|> 如果缓存中已存在,则表示已进行提前代理,此处跳过代理。
--|> 详情参见循环依赖相关篇章。
--> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
--|> 参见《分支 wrapIfNecessary》。
|
循环依赖场景中提前创建 AOP 流程
源码摘录
1
2
3
4
5
6
7
8
9
| // org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference
@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
// 构建缓存 key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 缓存到变量。在后续该 bean 的标准创建流程中,会根据缓存判断是否已进行提前创建。
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
|
主流程
1
2
3
4
5
6
7
8
9
10
11
12
| --> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
--> org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference
--> for-each smartInstantiationAwares 遍历 SmartInstantiationAwareBeanPostProcessor,调用接口方法`SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference`。
--> AOP:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference
--> 构建缓存 key
--|> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getCacheKey
--> 缓存到变量`AbstractAutoProxyCreator#earlyProxyReferences`中。
--|> `this.earlyProxyReferences.put(cacheKey, bean);`
--|> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#earlyProxyReferences
--|> 在后续该 bean 的标准创建流程中,会根据缓存判断是否已进行提前创建。
--> AOP 包装。
--|> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
|
AOP 代理逻辑
源码摘录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| // org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
|
主流程
下文分析基于 Spring 注解@Aspect定义的切面。
AspectJExpressionPointcut实现了接口ExpressionPointcut,ClassFilter,IntroductionAwareMethodMatcher。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
| // org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
--> 构建缓存 key。
--|> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getCacheKey
--> 循环引用判断,默认满足条件。
--|> `this.earlyProxyReferences.remove(cacheKey) != bean`
--> 如果不满足该条件,则直接返回 bean。
--|> return bean;
--|> 提前创建对象阶段,已完成构建 AOP 代理。
--|> 此处无需构建 AOP 代理。
--|> 在调用链上层的`org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean`中,会直接使用提前创建阶段创建的对象。
--|> 与`(exposedObject == bean)`有关,在方法`AbstractAutowireCapableBeanFactory#doCreateBean`中。
--> `SmartInstantiationAwareBeanPostProcessor`实现类中的接口方法`BeanPostProcessor#postProcessAfterInitialization`会直接返回入参中的 bean,或仅在非循环依赖的场景中构建代理。
--> AbstractAutoProxyCreator(AnnotationAwareAspectJAutoProxyCreator/AspectJAwareAdvisorAutoProxyCreator/InfrastructureAdvisorAutoProxyCreator) 仅在非循环依赖的场景中构建代理。
--> AutowiredAnnotationBeanPostProcessor 直接返回入参中的 bean
--> 因此,在循环依赖场景中,如果 AOP 代理符合预期,则条件`exposedObject == bean`成立。
--> 另,存在不符合预期的场景,即`AsyncAnnotationBeanPostProcessor`。其非`SmartInstantiationAwareBeanPostProcessor`实现类,因此在提前创建阶段与正式创建阶段的`BeanPostProcessor#postProcessAfterInitialization`中均会构建 AOP 代理。
--> 如果满足上述条件,则构建 AOP 代理。
--|> wrapIfNecessary(bean, beanName, cacheKey);
--|> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
--> 如果自定义代理逻辑(扩展点)的缓存`AbstractAutoProxyCreator#targetSourcedBeans`中存在 key,则直接返回对象,不再代理。该缓存在`AbstractAutoProxyCreator#postProcessBeforeInstantiation`阶段构建。
--> 判断该 bean 是否需要代理。首先查询判断结果的缓存`AbstractAutoProxyCreator#advisedBeans`,其次实际判断。
--|> 参见"AbstractAutoProxyCreator#postProcessBeforeInstantiation"阶段逻辑。
--> 获取适用于该 bean 的 Advisor。
--> getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
--|> org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
--> 获取适用于该 bean 的 Advisor。
--|> org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
--> 获取全量的 advisor。
--|> org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
--|> "AbstractAutoProxyCreator#postProcessBeforeInstantiation"阶段逻辑。
--> 从全量 advisor 中筛选适用于该 bean 的。
--|> org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
--> 缓存 beanName。`ProxyCreationContext.setCurrentProxiedBeanName(beanName);`
--> 根据 bean class 筛选。
--|> org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply
--> for-each advisors。遍历 advisors,筛选满足条件的`IntroductionAdvisor`。
--> 条件1:`candidate instanceof IntroductionAdvisor`
--> 条件2:`canApply(candidate, clazz)`
--> canApply(advisor, targetClass, false);
--|> org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Advisor, java.lang.Class<?>, boolean)
--> 参见下文。
--> for-each advisors。遍历 advisors,筛选满足条件的非`IntroductionAdvisor`。
--> 条件1:`candidate instanceof IntroductionAdvisor`
--> 条件2:`canApply(candidate, clazz, hasIntroductions)`
--|> org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Advisor, java.lang.Class<?>, boolean)
--> 参见下文。
--> 重置 beanName 缓存。`ProxyCreationContext.setCurrentProxiedBeanName(null);`
--> 扩展 Advisor。
--|> org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#extendAdvisors
--|> 如果存在 Spring AOP Advisor,则增加1个`ExposeInvocationInterceptor.ADVISOR`,其实现了`PriorityOrdered`,优先级最高。
--|> 作用是将当前方法调用暴露为线程本地对象。
--|> 判断条件`org.springframework.aop.aspectj.AspectJProxyUtils#isAspectJAdvice`
--> org.springframework.aop.aspectj.AspectJProxyUtils#makeAdvisorChainAspectJCapableIfNecessary
--> 排序,适用稳定的自定义拓扑排序。使用了排序器`org.springframework.core.annotation.AnnotationAwareOrderComparator#INSTANCE`。
--|> org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator#sortAdvisors
--|> 使用了`AspectJPrecedenceComparator`和`AnnotationAwareOrderComparator`。
--|> 如果A和B在不同的方面中定义,那么排序值最低的方面中的通知具有最高的优先级。
--|> 如果A和B在同一个方面中定义,如果A或B中的一个是after通知的形式,那么在方面中最后声明的通知具有最高优先级。如果A和B都不是after通知的形式,那么在方面中首先声明的通知具有最高优先级。
--|> 重要:此比较器与AspectJ的PartialOrder排序实用程序一起使用。
--|> 因此,与普通的Comparator不同,这个Comparator的返回值为0意味着我们不关心排序,也不是说两个元素必须排序相同。
--> 如果未找到 advisor,则返回空变量`AbstractAutoProxyCreator#DO_NOT_PROXY`。
--> 否则,返回找到的 advisor。
--> 如果已找到适用的 advisor,则构建 AOP 代理,并在缓存`AbstractAutoProxyCreator#advisedBeans`为 true。
--> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
--> 在 BeanDefinition 中配置属性`org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass`,值为 beanClass。
--> new ProxyFactory();
--> ProxyFactory 接口配置,待补充。
--> 构建 advisor。
--|> org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#buildAdvisors
--> 获取公共 advisor。缓存在`org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#interceptorNames`。
--> for-each advisors,遍历 advisors,将其包装为 Advisor。前面步骤获取的 advisor 的类型允许非 Advisor,例如`Advice`和`MethodInterceptor`。
--> 创建代理。
--|> proxyFactory.getProxy(classLoader);
--> createAopProxy().getProxy(classLoader);
--|> Cglib 使用的 interceptor 有,其中最关键的是`DynamicAdvisedInterceptor`。
--> 0 = {CglibAopProxy$DynamicAdvisedInterceptor@8244}
--> 1 = {CglibAopProxy$StaticUnadvisedInterceptor@8249}
--> 2 = {CglibAopProxy$SerializableNoOp@8255}
--> 3 = {CglibAopProxy$StaticDispatcher@8252}
--> 4 = {CglibAopProxy$AdvisedDispatcher@8225}
--> 5 = {CglibAopProxy$EqualsInterceptor@8256}
--> 6 = {CglibAopProxy$HashCodeInterceptor@8257}
--> 如果未找到 advisor,即``AbstractAutoProxyCreator#DO_NOT_PROXY``,则在缓存`AbstractAutoProxyCreator#advisedBeans`为 false
`InstantiationModelAwarePointcutAdvisorImpl`实现了`InstantiationModelAwarePointcutAdvisor`,`PointcutAdvisor`,`Advisor`。
|
关键方法介绍
AopUtils#canApply 方法介绍
源码摘录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Advisor, java.lang.Class<?>, boolean)
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
|
主流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| // org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Advisor, java.lang.Class<?>, boolean)
--> 如果 advisor 是`IntroductionAdvisor`实例,则使用类级别过滤器匹配。
--> `((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);`,略。
--> 如果 advisor 是`PointcutAdvisor`实例,Spring 注解`@Aspect`定义的切面均为`PointcutAdvisor`,具体是`InstantiationModelAwarePointcutAdvisor`。
--> 使用`Pointcut`条件匹配。
--|> org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)
--> 首先使用类级别过滤器匹配,如果不满足,则直接返回 false。
--> 获取类级别过滤器 ClassFilter。
--|> org.springframework.aop.aspectj.AspectJExpressionPointcut#getClassFilter
--> org.springframework.aop.aspectj.AspectJExpressionPointcut#obtainPointcutExpression
--> 如果`AspectJExpressionPointcut#pointcutExpression`为空,则初始化,否则直接返回。
--|> 第1次获取时为空,需要构建。
--> 获取类加载器。优先使用 beanFactory 的类加载器,略。
--> 构建`PointcutExpression`。
--|> org.springframework.aop.aspectj.AspectJExpressionPointcut#buildPointcutExpression
--> 初始化`PointcutParser`。
--|> org.springframework.aop.aspectj.AspectJExpressionPointcut#initializePointcutParser
--> 使用`org.aspectj.weaver.tools.PointcutParser`。
--|> PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(SUPPORTED_PRIMITIVES, classLoader);
--> new PointcutParser(supportedPointcutKinds);
--> 注册`BeanPointcutDesignatorHandler`到`PointcutParser`中。
--|> 其作用是解析 Spring 扩展的`bean()`切点,示例`@Before("bean(myService)")`。
--> parser.registerPointcutDesignatorHandler(new BeanPointcutDesignatorHandler());
--> 处理 pointcutParameters,略。
--> 解析表达式并返回`PointcutExpression`。
--|> org.aspectj.weaver.tools.PointcutParser#parsePointcutExpression(java.lang.String, java.lang.Class<?>, org.aspectj.weaver.tools.PointcutParameter[])
--> 使用类级别过滤器匹配。
--|> 下文分析基于 Spring 注解`@Aspect`定义的切面。
--|> org.springframework.aop.aspectj.AspectJExpressionPointcut#matches(java.lang.Class<?>)
--> org.aspectj.weaver.internal.tools.PointcutExpressionImpl#couldMatchJoinPointsInType
--> 代理相关逻辑,略。
--> 获取 bean class 实现的所有接口。
--> for-each classes 遍历 bean class 与其实现的接口,获取 class 中定义的方法,进行方法级别匹配,如果满足,则直接返回 true。
--> 获取 class 中定义的方法。`ReflectionUtils.getAllDeclaredMethods(clazz);`
--> for-each methods,进行方法级别匹配
--> org.springframework.aop.aspectj.AspectJExpressionPointcut#matches(java.lang.reflect.Method, java.lang.Class<?>, boolean)
--> 否则,返回 false。
--> 其它场景,返回`true`。
|
END