spring源碼分析——Aop的流程


 

  上面章節我們花費了大量的時間分析IOC,控制反轉,反轉控制對象的創建以及維護對象之間的依賴關系,對象的銷毀

1:對象的創建,加載並解析xml文件或者注解,生成BeanDefinition對象,實例化BeanDefinitionRegistryPostProcessor並調用重寫方法,實例化並注冊BeanPostProcessor 

的后置接口,預實例化非懶加載的單例對象。

2:維護對象的依賴關系, set注入、構造器注入、@Autowired 的依賴注入等

3:對象的銷毀,注冊可銷毀的回調接口,以及銷毀接口的調用

 

一:Aop的使用

下面我們來重點分析一下Aop的實現原理,首先我們來看一下面向切面編程的使用,

 

 

 

 

測試代碼:

 

 從運行結果看方法被攔截,說明代理成功:

 

 

 

二:源碼層面分析Aop

1:看一下開啟Aop的配置具體做了什么,這是一個自定義標簽aop,是通過命名空間加載的handler處理類

 

 

spring.handlers處理類

 

 

 

public class AopNamespaceHandler extends NamespaceHandlerSupport {

	/**
	 * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
	 * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
	 * and '{@code scoped-proxy}' tags.
	 * AopNamespaceHandler 命名空間handler實例化完成后,會調用init進行初始化,
	 * 在初始化中完成各種元素解析器的注冊
	 */
	@Override
	public void init() {
		// In 2.0 XSD as well as in 2.1 XSD.
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace as of 2.1
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

}

    

處理器init方法中,有一個AspectJAutoProxyBeanDefinitionParser的解析器:

 

 

 

 

 

 

 

 AnnotationAwareAspectJAutoProxyCreator 這個類將會被注冊到BeanDefinitionMaps中

 

 

 

 

 到這里動態代理的BeanPostProcessor以BeanDefinition的形式注冊到BeanDefinitionMaps中就完成了。

 

2:在refresh方法中,registryBeanPostProcessor方法中,會實例化所有的BeanPostProcessor對象,並注冊到beanPostProcessors中,以備后續使用。

 

3:使用BeanPostProcessor創建代理對象

創建代理對象是在initializeBean方法中beanPostProcessor的after接口中進行的

 

 調用代理PostProcessor的后置接口方法:

 

 

這wrapIfNecessary中進行代理:

 

 

獲取切面通知,並創建代理,然后返回,大致的流程是這樣,我們再來看一下細節部分:

 

 

獲取切面通知:

 

 

 

 尋找所有切面類:

 

 

尋找切面類的所有增強:

 

 

搜集切面類的所有非切點方法:

 

 

 

 每個Advisor維護了Advice對象

 

 

getAdvice方法:

 

 根據注解類型 判斷 是創建Before 、After、Around 的通知器Advice

到這里就把所有的@Aspect類里所有的非切點方法,搜集到了,封裝成Advisor對象,每個Advisor對象維護了一個Advice對象。

 

看一下和當前bean的匹配

 

 

 

 

匹配當前類:

 

 

 

 

 

 將匹配的Advisor返回,到這里所有匹配的bean的增強通知器Advisor都被搜集到了。

 

下一步就是創建代理:

 

 

 

 

 

 

 

 

 

 

 

 

到這里代理對象創建完成。

 

 對象已經被代理

 

 

所以注冊到一級緩存中的對象也是代理對象

 

4:調用某個接口實際上就是調用代理的invoke

 

 

 

 

 

 

先調用after的Advice

 

 

再調用around的Advice

 

 

進入around的切面方法:

 

 調到before的Advicefang方法:

 

 調用before的切面方法:

 

 

然后調到真正的test方法

 

最后調到after的通知方法,在finally代碼塊中:

 

 

 

 

到這里調用鏈的調用就結束了。

 

總結:aop的流程主要有一下步驟:

1:注冊BeanDefinition,在xml中配置aop自定義標簽或者注解開啟Enable都會注冊動態代理的BeanPostProcessor接口

2:在registryBeanPostProcessor中實例化對象並注冊到beanPostProcessors集合中,以備后面使用

3:在預實例化第一個bean的時候就會搜集所有的Aspect切面信息,然后獲取切面信息的Advisor,緩存起來

4:拿所有的bean匹配Advisor信息,如果能夠匹配上,把Advisor的對象放入放入中返回,如果不為空,則創建該bean的代理對象。

5:當調用該bean的方法時,會調用到橫切面上,然后調用鏈會依次調用鏈中的放入,對方法進行增強。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM