Aop相關注解
- @EnableTransactionManagement
- @EnableAspectJAutoProxy
- @EnableAsync
- ...
從注解切入來看看這些注解都干了什么
@Import注解作用簡述
注入的類一般繼承ImportSelector或者ImportBeanDefinitionRegistrar接口
- 繼承ImportSelector接口:selectImports方法返回的類名會被解析成bean
- 繼承ImportBeanDefinitionRegistrar接口:會在解析階段執行registerBeanDefinitions方法
Spring解析流程可以看我之前寫的博文 《Spring之ConfigurationClassPostProcessor解析流程》重點講解了@Import等注解是如何解析的
@EnableAsync注解
@EnableAsync注解作用
- 注入一個類型為AsyncAnnotationBeanPostProcessor的BeanPostProcessor
@EnableTransactionManagement注解
@EnableTransactionManagement注解作用
- 注入一個類型為InfrastructureAdvisorAutoProxyCreator的BeanPostProcessor
- 注入事務相關的bean
@EnableAspectJAutoProxy
@EnableAspectJAutoProxy注解作用
- 注入一個類型為AnnotationAwareAspectJAutoProxyCreator的bpp
@EnableTransactionManagement和@EnableAspectJAutoProxy注解的淵源
從方法的角度
兩個類都是通過AopConfigUtils.registerXXX方法注入一個bpp到spring中
注意點:AopConfigUtils的register方法存在三個優先級,如果spring調用了多次register方法,spring會保留優先級最高的bpp(beanName為org.springframework.aop.config.internalAutoProxyCreator)。比如Spring中同時存在@EnableTransactionManagement和@EnableAspectJAutoProxy注解,但因為@EnableAspectJAutoProxy注解注入的bpp的優先級高于@EnableTransactionManagement注解注入的bpp,所以spring只有一個類型為AnnotationAwareAspectJAutoProxyCreator的bean,而不存在類型為InfrastructureAdvisorAutoProxyCreator的bean
相關源碼AopConfigUtils#registerOrEscalateApcAsRequired
從類的的角度
兩個bpp都繼承AbstractAutoProxyCreator,然而Spring動態代理相關的邏輯都是在這個類中處理的,所有我們可以認為@EnableTransactionManagement和@EnableAspectJAutoProxy注解實現動態代理的邏輯是一樣的。
注解實現動態代理的時機
@EnableAsync注解
我們從前文中了解到@EnableAsync注解會注入一個類型為AsyncAnnotationBeanPostProcessor的bpp,我們來查看源碼
我們通過類的繼承關系,關注其祖父類(AbstractAdvisingBeanPostProcessor)的postProcessAfterInitialization方法
@EnableTransactionManagement和@EnableAspectJAutoProxy注解
通過上文的分析,我們主要查看AbstractAutoProxyCreator的postProcessAfterInitialization方法
通過源碼,我們得出以下幾個結論
- 幾個注解注入的bpp都是通過postProcessAfterInitialization方法進行動態代理
- Spring是通過ProxyFactory這個類完成動態代理的
Spring是如何解決多個bpp對bean進行處理的順序問題
我們回過頭查看@EnableAsync注解注入的bpp的postProcessAfterInitialization方法
從碼義上來說,@EnableAsync注解進行AOP動態代理優先級是比較低的,那Spring是怎么處理,讓優先級比較低的bpp稍后執行呢?
我們查看源碼PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
Spring會對所有的bpp進行排序,然后按順序加入到列表中,優先級較高的優先加入,優先處理
這里的比較器使用的是AnnotationAwareOrderComparator,這個比較器大致分成以下步驟
- bpp是否繼承PriorityOrdered接口,如果都繼承PriorityOrdered接口,比較getOrder方法返回的值,值越小,優先級越高
- bpp是否繼承Ordered接口,如果都繼承Ordered接口,比較getOrder方法返回的值,值越小,優先級越高
- bpp所屬class上是否存在@Order注解,如果存在,比較@Order注解設置的值,值越小,優先級越高
- 其他
這里需要注意的是,如果一個bpp繼承PriorityOrdered接口,getOrder方法返回的值為100,另外一個bpp繼承Ordered接口,getOrder方法返回的值為1,按照第一優先級規則,還是繼承PriorityOrdered接口的bpp優先級高
我們查看三個注解相關源碼
@EnableAsync注解order默認值是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE)
@EnableTransactionManagement注解order默認值是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE)
@EnableAspectJAutoProxy注解未開啟設置
默認的情況下,@EnableAsync和@EnableTransactionManagement注解注入的bpp都繼承Ordered接口,并且getOrder方法返回的值都是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE),默認情況下優先級一致,但是@EnableTransactionManagement注解注入bpp的時候,對order值進行了手動設置,保證了如果同時存在@EnableAsync和@EnableTransactionManagement注解的情況下,@EnableTransactionManagement注解注入的bpp進行AOP動態代理,@EnableAsync注解注入的bpp進行增強。如果只存在@EnableAsync注解,則相關bpp進行AOP動態代理
相關源碼AopConfigUtils#registerOrEscalateApcAsRequired
這里需要說明一下,雖然@EnableAspectJAutoProxy注解不能指定order值,但是有默認值,默認值也是Ordered.LOWEST_PRECEDENCE(Integer.MAX_VALUE),@EnableTransactionManagement和@EnableAspectJAutoProxy注解從一定程度上來說,這些可以指定的參數是互補的,因為它們進行AOP動態代理的是操作是通過共同父類AbstractAutoProxyCreator完成的
總結
- @EnableTransactionManagement,@EnableAspectJAutoProxy,@EnableAsync注解都有可能產生AOP動態代理
- @EnableTransactionManagement,@EnableAspectJAutoProxy注解注入的bpp,都是依靠AbstractAutoProxyCreator這個類完成動態代理的。如果它們同時存在,Spring中只會存在一個優先級更高的bpp。這兩個注解指定的參數是互補的,對于特定需求,可以進行擴展
- 幾個注解注入的bpp,都是Spring執行到postProcessAfterInitialization方法階段,完成AOP動態代理
- Spring通過registerOrEscalateApcAsRequired方法手動修改了@EnableTransactionManagement,@EnableAspectJAutoProxy注入的bpp的order值,所以執行順序優先于@EnableAsync注入的bpp
- 幾個注解都是通過ProxyFactory這個類,以策略模式完成AOP動態代理(我們下一篇文章將重點講解這個類)