上面章節我們花費了大量的時間分析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的方法時,會調用到橫切面上,然后調用鏈會依次調用鏈中的放入,對方法進行增強。