Spring源码-Aspect-源码-02

总结摘要
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`。
            --> AOPorg.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