在Spring AOP - 註解方式使用介紹(長文詳解)中,做者介紹了Spring AOP 註解方式的使用方式。算是給我們的Spring AOP 源碼分析開了個頭,作了一點知識點的鋪墊。html
在開始學習Spring AOP的源碼以前,若是你尚未學習過Spring IoC的源碼,最好先去學習下Spring IoC。java
Spring AOP 只做用於Spring Bean 的特性說明了Spring AOP和Spring IOC 的關係,AOP 依賴於 IOC 容器來管理,後面的源碼分析也會涉及到Spring IoC 的源碼內容。spring
下面,假設你已經學習過Spring IoC 的相關內容和Spring AOP的相關使用,讓咱們開始吧。mybatis
本文耗費了做者大量心力,但願能對你有所幫助。app
咱們前面一直說的Spring AOP源碼解析,源碼這麼多,咱們真正關注的內容是什麼?框架
Spring AOP的功能是什麼?從使用上直白的說,就是根據咱們的配置來生成代理類,攔截指定的方法,將指定的advice織入。ide
咱們應該關注的內容總結下來就是:源碼分析
另外,整個源碼解析的內容過多,爲了讀者的閱讀體驗和本身的時間安排。我將按照上面的總結的三點,分三篇向您解讀。post
本文的源碼解析是以AOP註釋方式使用來做爲例子講解的,和其餘方式主要是在於觸發入口不一樣,核心的流程仍是差很少的。但願讀者們可以舉一反三。學習
咱們在Spring AOP - 註解方式使用介紹(長文詳解)中介紹了@EnableAspectJAutoProxy
註解,是用來開啓 Spring AOP註解的使用。這個的做用就是自動讓 ioc 容器中的全部 advisor 來匹配方法,advisor 內部都是有 advice 的,讓它們內部的 advice 來執行攔截處理(注:advisor 能夠就當作 pointcut + advise的一個組合對象)。引用這個註解的英文翻譯就是開啓自動代理。
那麼裏面的玄機是什麼呢?
咱們進去先進到這個註解裏面看看,
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
複製代碼
@Import(AspectJAutoProxyRegistrar.class)
使用@Import
註解將 AspectJAutoProxyRegistrar
注入到 IoC 容器當中。
對這個註解不熟悉的能夠去了解一下 @Import Annotation in Spring Framework
咱們看一看這個AspectJAutoProxyRegistrar
,
注意,這個類實現了ImportBeanDefinitionRegistrar
接口。
這個接口是一個Spring 很強大的擴展接口,它的做用是:
Register additional bean definitions when processing @Configuration classes. Useful when operating at the bean definition level (as opposed to @Bean method/instance level) is desired or necessary.
就是說,它須要和@Configuration
配合使用,在@Configuration
以前已註冊的Bean,能夠由ImportBeanDefinitionRegistrar
接口來處理,這個接口提供了以下一個方法:
void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) 複製代碼
這個方法能夠拿到@Import
的這個class的Annotation Metadata
,以及此時的BeanDefinitionRegistry
對象,經過BeanDefinitionRegistry
就能夠拿到目前全部註冊的BeanDefinition,能夠自定義邏輯來動態註冊一些你以爲必要的BeanDefinition。
PS: 不少開源框架與Spring 集成的時候都擴展了這個接口,好比Apollo的ApolloConfigRegistrar 、mybatis的MapperScannerRegistrar等等
在AspectJAutoProxyRegistrar
中,實際上就是將AspectJAnnotationAutoProxyCreator
的BeanDefinition
註冊到IoC 容器當中。
下面是AopConfigUtils
中執行註冊的邏輯代碼片斷。
先來一條分割線,理解完上面的流程以後,咱們繼續來思考。
爲何把AspectJAnnotationAutoProxyCreator
注入到Spring IoC 容器中,自動代理就開啓了呢?
讓咱們來尋找這個觸發點。
首先,咱們來看一下AspectJAnnotationAutoProxyCreator
的繼承結構。
有沒有發現,AspectJAnnotationAutoProxyCreator
竟然是一個BeanPostProcessor
!
學習過 Spring IoC 以後的你,應該對這個類極其的敏感。
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
複製代碼
咱們先回顧思考下代理模式的實現思路:(接口) + 真實實現類 + 代理類。
是否是要先有了真實的實現類,纔可以生成代理類?!
在Spring IoC - 依賴注入 源碼解析中咱們介紹了Spring Bean 建立的過程,在執行完 Step1 建立實例對象createBeanInstance()
和 Step2 屬性裝配populateBean()
以後,咱們纔算獲得一個真正的實現類。
在Step3 initializeBean()
中,IoC容器會處理Bean初始化以後的各類回調事件,而後返回一個「可能通過加工」的bean對象。
其中就包括了BeanPostProcessor
的 postProcessBeforeInitialization
回調 和 postProcessAfterInitialization
回調。
而AspectJAnnotationAutoProxyCreator
偏偏是一個BeanPostProcessor
(原諒我又重複了一次),那就很容易聯想到,Spring AOP 就是在這一步,進行代理加強!
那麼接下來,咱們就來看看這裏面的玄機。
能夠看到實際回調的 postProcessBeforeInitialization
和 postProcessAfterInitialization
這兩個方式是在AbstractAdvisorAutoProxyCreator
中 override 的。
源碼位置:AbstractAdvisorAutoProxyCreator
JavaDoc 很清楚的註明了postProcessAfterInitialization
會執行建立代理類的操做,用配置的interceptors 來建立一個代理類,而且告訴咱們去看getAdvicesAndAdvisorsForBean
,看來這會是一個關鍵方法,這裏咱們先不急,繼續往下看wrapIfNecessary
方法。
源碼位置:AbstractAutoProxyCreator#wrapIfNecessary(..)
這個方法裏面有核心的就是兩個點,我在上圖中分別用**** TODO-1 ****
和**** TODO-2 ****
標識出來了。
TODO-1
就是獲取當前的Spring Bean 適配的 advisors。
TODO-2
就是建立代理類。
咱們接下去的章節就是詳細講解這兩個TODO
的內容。咱們下次再會。
若是本文有幫助到你,但願能點個贊,這是對個人最大動力。