天天看點

Spring AOP解析過程

文章目錄

      • Step 1:初始化解析器 AspectJAutoProxyBeanDefinitionParser
        • 1.擷取增強方法

Step 1:初始化解析器 AspectJAutoProxyBeanDefinitionParser

AspectJAutoProxyBeanDefinitionParser:遇到 aspectj-autoproxy 注解時,用該解析器進行解析,即:

<!-- 聲明自動為spring容器中那些配置@aspectJ切面的bean建立代理,織入切面。-->
<aop:aspectj-autoproxy/> 
           

###Step 2:調用AspectJAutoProxyBeanDefinitionParser的parse函數注冊AnnotationAwareAspectJAutoProxyCreator類(代理生成器,在解析配置檔案時候)

  1. 需要考慮到自定義代理生成器與當時不一緻,需要根據優先級來決定使用哪一個
  2. 自定義代理生成器常用的有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類

  1. 擷取增強器等解析操作是Spring解析配置檔案的時候,此時擷取所有增強器并建立代理
  2. 調用Bean方法的時候調用代理的invoke方法
AOP有三種植入切面的方法:
  • 其一是編譯期織入,這要求使用特殊的Java編譯器,AspectJ是其中的代表者;
  • 其二是類裝載期織入,而這要求使用特殊的類裝載器,AspectJ和AspectWerkz是其中的代表者;
  • 其三為動态代理織入,在運作期為目标類添加增強生成子類的方式,Spring AOP采用動态代理織入切面。