11.Spring之AOP底層源碼解析(下)

ProxyFactory選擇cglib或jdk動態代理原理

ProxyFactory在生成代理對象之前需要決定到底是使用JDK動態代理還是CGLIB技術:

// config就是ProxyFactory對象

// optimize爲true,或proxyTargetClass爲true,或用戶沒有給ProxyFactory對象添加interface
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
	Class<?> targetClass = config.getTargetClass();
	if (targetClass == null) {
		throw new AopConfigException("TargetSource cannot determine target class: " +
				"Either an interface or a target is required for proxy creation.");
	}
    // targetClass是接口,直接使用Jdk動態代理
	if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
		return new JdkDynamicAopProxy(config);
	}
    // 使用Cglib
	return new ObjenesisCglibAopProxy(config);
}
else {
    // 使用Jdk動態代理
	return new JdkDynamicAopProxy(config);
}

代理對象創建過程

JdkDynamicAopProxy

  1. 在構造JdkDynamicAopProxy對象時,會先拿到被代理對象自己所實現的接口,並且額外的增加SpringProxy、Advised、DecoratingProxy三個接口,組合成一個Class[],並賦值給proxiedInterfaces屬性
  2. 並且檢查這些接口中是否定義了equals()、hashcode()方法
  3. 執行Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this),得到代理對象,JdkDynamicAopProxy作爲InvocationHandler,代理對象在執行某個方法時,會進入到JdkDynamicAopProxy的invoke()方法中

ObjenesisCglibAopProxy

  1. 創建Enhancer對象
  2. 設置Enhancer的superClass爲通過ProxyFactory.setTarget()所設置的對象的類
  3. 設置Enhancer的interfaces爲通過ProxyFactory.addInterface()所添加的接口,以及SpringProxy、Advised、DecoratingProxy接口
  4. 設置Enhancer的Callbacks爲DynamicAdvisedInterceptor
  5. 最後創建一個代理對象,代理對象在執行某個方法時,會進入到DynamicAdvisedInterceptor的intercept()方法中

代理對象執行過程

  1. 在使用ProxyFactory創建代理對象之前,需要往ProxyFactory先添加Advisor
  2. 代理對象在執行某個方法時,會把ProxyFactory中的Advisor拿出來和當前正在執行的方法進行匹配篩選
  3. 把和方法所匹配的Advisor適配成MethodInterceptor
  4. 把和當前方法匹配的MethodInterceptor鏈,以及被代理對象、代理對象、代理類、當前Method對象、方法參數封裝爲MethodInvocation對象
  5. 調用MethodInvocation的proceed()方法,開始執行各個MethodInterceptor以及被代理對象的對應方法
  6. 按順序調用每個MethodInterceptor的invoke()方法,並且會把MethodInvocation對象傳入invoke()方法
  7. 直到執行完最後一個MethodInterceptor了,就會調用invokeJoinpoint()方法,從而執行被代理對象的當前方法

各註解對應的MethodInterceptor

  • @Before對應的是AspectJMethodBeforeAdvice,在進行動態代理時會把AspectJMethodBeforeAdvice轉成MethodBeforeAdviceInterceptor
    • 先執行advice對應的方法
    • 再執行MethodInvocation的proceed(),會執行下一個Interceptor,如果沒有下一個Interceptor了,會執行target對應的方法
  • @After對應的是AspectJAfterAdvice,直接實現了MethodInterceptor
    • 先執行MethodInvocation的proceed(),會執行下一個Interceptor,如果沒有下一個Interceptor了,會執行target對應的方法
    • 再執行advice對應的方法
  • @Around對應的是AspectJAroundAdvice,直接實現了MethodInterceptor
    • 直接執行advice對應的方法,由@Around自己決定要不要繼續往後面調用
  • @AfterThrowing對應的是AspectJAfterThrowingAdvice,直接實現了MethodInterceptor
    • 先執行MethodInvocation的proceed(),會執行下一個Interceptor,如果沒有下一個Interceptor了,會執行target對應的方法
    • 如果上面拋了Throwable,那麼則會執行advice對應的方法
  • @AfterReturning對應的是AspectJAfterReturningAdvice,在進行動態代理時會把AspectJAfterReturningAdvice轉成AfterReturningAdviceInterceptor
    • 先執行MethodInvocation的proceed(),會執行下一個Interceptor,如果沒有下一個Interceptor了,會執行target對應的方法
    • 執行上面的方法後得到最終的方法的返回值
    • 再執行Advice對應的方法

AbstractAdvisorAutoProxyCreator

DefaultAdvisorAutoProxyCreator的父類是AbstractAdvisorAutoProxyCreator。

AbstractAdvisorAutoProxyCreator非常強大以及重要,只要Spring容器中存在這個類型的Bean,就相當於開啓了AOP,AbstractAdvisorAutoProxyCreator實際上就是一個BeanPostProcessor,所以在創建某個Bean時,就會進入到它對應的生命週期方法中,比如:在某個Bean初始化之後,會調用wrapIfNecessary()方法進行AOP,底層邏輯是,AbstractAdvisorAutoProxyCreator會找到所有的Advisor,然後判斷當前這個Bean是否存在某個Advisor與之匹配(根據Pointcut),如果匹配就表示當前這個Bean有對應的切面邏輯,需要進行AOP,需要產生一個代理對象。

@EnableAspectJAutoProxy

這個註解主要就是往Spring容器中添加了一個AnnotationAwareAspectJAutoProxyCreator類型的Bean。

AspectJAwareAdvisorAutoProxyCreator繼承了AbstractAdvisorAutoProxyCreator,重寫了findCandidateAdvisors()方法,AbstractAdvisorAutoProxyCreator只能找到所有Advisor類型的Bean對象,但是AspectJAwareAdvisorAutoProxyCreator除開可以找到所有Advisor類型的Bean對象,還能把@Aspect註解所標註的Bean中的@Before等註解及方法進行解析,並生成對應的Advisor對象。

所以,我們可以理解@EnableAspectJAutoProxy,其實就是像Spring容器中添加了一個AbstractAdvisorAutoProxyCreator類型的Bean,從而開啓了AOP,並且還會解析@Before等註解生成Advisor。

Spring中AOP原理流程圖

https://www.processon.com/view/link/5faa4ccce0b34d7a1aa2a9a5

 

本系列文章來自圖靈學院周瑜老師分享,本博客整理學習並搬運

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章