文章目錄
-
-
- Step 1:初始化解析器 AspectJAutoProxyBeanDefinitionParser
-
- 1.擷取增強方法
-
Step 1:初始化解析器 AspectJAutoProxyBeanDefinitionParser
AspectJAutoProxyBeanDefinitionParser:遇到 aspectj-autoproxy 注解時,用該解析器進行解析,即:
<!-- 聲明自動為spring容器中那些配置@aspectJ切面的bean建立代理,織入切面。-->
<aop:aspectj-autoproxy/>
###Step 2:調用AspectJAutoProxyBeanDefinitionParser的parse函數注冊AnnotationAwareAspectJAutoProxyCreator類(代理生成器,在解析配置檔案時候)
- 需要考慮到自定義代理生成器與當時不一緻,需要根據優先級來決定使用哪一個
- 自定義代理生成器常用的有DefaultAdvisorAutoProxyCreator和BeanNameAutoProxyCreator,其中DefaultAdvisorAutoProxyCreator 比較暴力 ,會把容器内所有的切面向所有的目标對象織入,而且切面隻能是顧問的形式。而BeanNameAutoProxyCreator比較友好,可以讓我們有選擇性的對目标對象和切面進行織入的操作,而且切面可以是顧問或者通知的形式。
###Step 3:由于AnnotationAwareAspectJAutoProxyCreator實作了BeanPostProcessor接口,則會在加載該Bean過程中會調用後處理方法(AbstractAutoProxyCreator類中)
1.擷取增強方法
第一步:擷取所有的增強器
(1)擷取所有的BeanName,其中包括父類的(遞歸查找)
(2)周遊所有BeanName,找出聲明為AspectJ注解的類
(3)若切面類是AspectJ的Singleton執行個體化模型,則表示切面隻有一個執行個體,則建立BeanFactoryAspectInstanceFactory工廠,否則建立PrototypeAspectInstanceFactory工廠(PrototypeAspectInstanceFactory繼承了BeanFactoryAspectInstanceFactory工廠)
(4)對每個AspectJ注解的類來根據工廠擷取增強器Advisor(顧問)清單
- Step 1:針對類中每個方法擷取增強器
- Step 2:增加同步執行個體化增強器(P185)
- Step 3:擷取DeclareParents注解(使用DeclareParentsAdvisor進行封裝)
擷取增強器Advisor清單過程(針對每個方法擷取增強器的流程)
(1)對aspectClass每個方法擷取該方法上的切點資訊(即Pointcut,查找Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class),并封裝在AspectJExpressionPointcut類中
(2)根據找到的每個切點資訊生成增強,所有的增強由Advisor的實作類InstantiationModelAwarePointcutAdvisorImpl統一封裝。
(3)在封裝類InstantiationModelAwarePointcutAdvisorImpl中調用this.aspectJAdvisorFactory的getAdvice的方法,該方法根據不同的注解類型封裝不同的增強器
- AtBefore注解(@Before)—>建立AspectJMethodBeforeAdvice:MethodBeforeAdviceInterceptor
- AtAfter注解(@After)—>建立AspectJAfterAdvice:由于AspectJAfterAdvice實作了攔截器,直接調用
- AtAfterReturning注解(@AfterReturning)—->建立AspectJAfterReturningAdvice
- AtAfterThrowing注解(@AfterThrowing)—>建立AspectJAfterThrowingAdvice
- AtAround注解(@Around)—>建立AspectJAroundAdvice
第二步:尋找比對的增強器
檢查目标類是否符合切點表達式
####2.建立代理
第一步:建立ProxyFactory來進行代理類的建立與處理
第二步:若設定proxyTarClass為false,則添加代理接口
第三步:将攔截器封裝成增強器
第四步:建立代理
a. 條件
若proxyTargetClass屬性為true,或者存在代理接口時使用CGLIB代理,否則使用JDK動态代理
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
b.JdkDynamicAopProxy類(實作了InvocationHandler接口)中的invoke方法
建立一個攔截器鍊,并一個個執行(如前面建立的增強器就此時執行)
c.CglibAopProxy類
- 擷取增強器等解析操作是Spring解析配置檔案的時候,此時擷取所有增強器并建立代理
- 調用Bean方法的時候調用代理的invoke方法
AOP有三種植入切面的方法:
- 其一是編譯期織入,這要求使用特殊的Java編譯器,AspectJ是其中的代表者;
- 其二是類裝載期織入,而這要求使用特殊的類裝載器,AspectJ和AspectWerkz是其中的代表者;
- 其三為動态代理織入,在運作期為目标類添加增強生成子類的方式,Spring AOP采用動态代理織入切面。