Aspect動態aop

[toc]spring

##使用講解緩存

  • 編寫aspect類,並使用@component加入spring的容器app

  • aop:aspectj-autoproxy/ 會在spring建立bean的時候應用@Aspect註解的切點和通知post

##源碼解析ui

想把全部的@aspect註解的bean 轉換成advisor ,而後從中找到匹配當前bean的advosor,建立代理類this

入口

AspectJAwareAdvisorAutoProxyCreator是繼承與SmartInstantiationAwareBeanPostProcessor接口的,該接口會在建立完bean以後執行postProcessBeforeInstantiation方法,spring容器中實際返回的對象是通過該方法處理後的對象,也就是代理對象,每一個bean可能會適配多個切面,spring的處理時將全部的切面轉換成攔截器(MethodInteceptor),而後將攔截器生成一個鏈,按照指定的順序執行。.net

  • 相關類圖代理

  • 啓動方法code

AbstractAutoProxyCreator.postProcessBeforeInstantiation{}

獲取切面 InstantiationModelAwarePointcutAdvisorImpl

查找全部非@PointCut註解的方法,若是方法上面有{Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class}這些註解,則認爲這個是一個advice,就會去建立一個切面,經過方法上面註解的切點表達式來建立切點,在建立完以後會統一的緩存下來的(BeanFactoryAspectJAdvisorsBuilder.advisorsCache)。component

AbstractAutoProxyCreator.postProcessBeforeInstantiation{}->

AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean{}->

AbstractAdvisorAutoProxyCreator.findEligibleAdvisors{}->

AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors{}-> 

BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors{}

ReflectiveAspectJAdvisorFactory.getAdvisors(new PrototypeAspectInstanceFactory(this.beanFactory, beanName)){}->

ReflectiveAspectJAdvisorFactory.getAdvisor{}->

new InstantiationModelAwarePointcutAdvisorImpl{}->

切面排序 AspectJPrecedenceComparator

先將全部的切面獲取出來,而後篩選出匹配的切面,而後使用AspectJPrecedenceComparator排序切面

AbstractAdvisorAutoProxyCreator.findEligibleAdvisors{}->

AspectJAwareAdvisorAutoProxyCreator.sortAdvisors{}->

new PartiallyComparableAdvisorHolde(new AspectJPrecedenceComparator()){}->

獲取pointCut AspectJExpressionPointcut

ReflectiveAspectJAdvisorFactory.getAdvisor{}->

ReflectiveAspectJAdvisorFactory.getPointcut{}->

new AspectJExpressionPointcut{}

###獲取advice

(AspectJMethodBeforeAdvice、AspectJAfterAdvice、AspectJAfterReturningAdvice、AspectJAfterThrowingAdvice,AspectJAroundAdvice)

ReflectiveAspectJAdvisorFactory.getAdvisor{}->

new InstantiationModelAwarePointcutAdvisorImpl{}->

InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice{}->

ReflectiveAspectJAdvisorFactory.getAdvice{

    new AspectJMethodBeforeAdvice

    new AspectJAfterAdvice

    new AspectJAfterReturningAdvice

    new AspectJAfterThrowingAdvice

    new AspectJAroundAdvice

}

獲取匹配的切面

  • 代理目標類 targetSource

spring中並非直接代理目標對象的,直接代理目標對象是沒法拓展的,必需要有一箇中間對象提供一些一致的操做,同時也能夠封裝一些特定場景的拓展,這中在spring中是很是常見的,如spring在建立bean的時候並非直接就建立目標的bean,而是經過一箇中間的對象BeanWrapper來提供統一的操做目標bean的方法。

  • 相關類圖

  • 參考資料:

spring-aop組件詳解——TargetSource目標源

  • 遍歷全部的切面,找到匹配的切面
AbstractAdvisorAutoProxyCreator.findEligibleAdvisors{}->

AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply{}->

AopUtils.findAdvisorsThatCanApply{}

AopUtils.canApply(Advisor advisor, Class<?> targetClass){}->

AopUtils.canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions){}->

AopUtils.canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions){}->

Pointcut.getMethodMatcher().matches{}

建立代理類

  • 相關類圖

  • 流程解析

在建立ProxyFactory工廠的時候會將相關配置都設置進來,該對象中封裝了兩種具體邏輯(JdkDynamicAopProxy、ObjenesisCglibAopProxy),真正獲取代理類是從這兩個類裏面獲取出來的,ProxyFactory實現了proxyConfig接口,因此自己就是一個配置類,在建立具體這兩個類的時候會將該自己傳遞過去。

AbstractAutoProxyCreator.postProcessBeforeInstantiation{}->

AbstractAutoProxyCreator.createProxy{}->

ProxyFactory.proxyFactory{}->//相關的配置信息會設置進去

DefaultAopProxyFactory.createAopProxy{}.getProxy{}->//JdkDynamicAopProxy、ObjenesisCglibAopProxy

JdkDynamicAopProxy 目標方法執行解析

  • 相關類圖

  • 解析流程1:將Advisor適配成MethodInterceptor

在proxyFactory中建立了一個DefaultAdvisorChainFactory ,該對象能夠講全部的advisor對象適配成MethodInterceptor對象。

MethodInterceptor對象能夠認爲是一個攔截器,這裏會將全部的攔截器組成一個攔截器鏈

JdkDynamicAopProxy.invoke{}->

ProxyFactory.getInterceptorsAndDynamicInterceptionAdvice{}->

DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice{}->

DefaultAdvisorAdapterRegistry.getInterceptors{}->//搞不懂一個切面爲何會被轉換成多個MethodInterceptor

AdvisorAdapter.getInterceptor{}->// AfterReturningAdviceAdapter 、 MethodBeforeAdviceAdapter 、ThrowsAdviceAdapte
  • 解析流程2:攔截器鏈的使用

接着上個流程,將攔截器鏈傳入ReflectiveMethodInvocation,執行具體方法的時候會執行ReflectiveMethodInvocation.proceed方法,該方法中會調用MethodInterceptor.invoke,同時將ReflectiveMethodInvocation對象傳遞過去,在具體的MethodInterceptor.invoke中通常會回調ReflectiveMethodInvocation.proceed,這樣就生成了一個由ReflectiveMethodInvocation對象鏈接的鏈。在ReflectiveMethodInvocation中定義了一個interceptorsAndDynamicMethodMatchers屬性,記錄當前全部須要執行的攔截器, currentInterceptorIndex記錄當前執行到的攔截器,每次回調都會加1,直到執行完畢。

JdkDynamicAopProxy.invoke{}->

ReflectiveMethodInvocation.proceed{}

MethodInterceptor.invoke(ReflectiveMethodInvocatione){}
  • 相關參考

Spring AOP深刻理解之攔截器調用

相關文章
相關標籤/搜索