javascript
轻轻松松看懂Spring AOP源码
輕輕松松看懂Spring AOP源碼
https://baijiahao.baidu.com/s?id=1596466083334197175&wfr=spider&for=pc
如果對spring的核心容器和JDK動態代理、CGLIB有所了解,接下來再看spring AOP源碼會比較容易。文中所有代碼片段截圖對應的spring版本是5.0。
本文內容曾首發于頭條。
首先來看個問題,spring在哪里使用了AOP?spring 實現AOP代碼的源頭在哪里?
spring AOP運用動態代理技術來創建和初始化代理對象。至于AOP代碼的源頭和入口,自然是和加載代理類的BeanDefinition和代理對象的創建、初始化有關。
1.spring AOP之加載和解析aop配置
先來看下加載BeanDefinition以及對aop配置的解析,下面是從容器開始啟動到解析BeanDefinitions的方法鏈:
然后我們直接定位到DefaultBeanDefinitionDocumentReader#parseBeanDefinitions,如下圖:
上圖中parseCustomElement是對非節點的解析,相關的節點解析自然是走178行代碼分支。該分支實際調用的是下圖中的代碼片段:
1361行代碼根據nameSpace匹配相應的handler,aop節點匹配的是右圖中的AopNamespaceHandler。1366行的parse調用的是其父類NamespaceHandlerSupport的parse方法,如下圖:
節點匹配的則是圖中右側的ConfigBeanDefinitionParser。來看下其實現:
上述代碼106行配置了用于創建代理對象的AspectJAwareAdvisorAutoProxyCreator,我們看完aop配置解析之后再來分析。
節點的子節點是,所以這里走118行的分支。然后就是對的子節點,等的解析。
讀到這里應該對AOP配置的解析有了大概的認識。但是你是否想過,解析的結果封裝在哪里了?是ParserContext。
ConfigBeanDefinitionParser#parseAspect調用了ConfigBeanDefinitionParser#parseAdvice,來看下其實現:
其中340行是最關鍵的,可以看到最終是通過創建RootBeanDefinition來封裝我們aop節點的配置信息,然后在349行將beanDefinition注冊到容器(BeanFactory)。
aop配置的解析就看到這里。下面來看aop中代理對象的創建、實例化等。
2.spring AOP之創建代理
aop創建代理對象的時機是在調用getBean首次從容器中獲取bean時。其實現
AbstractBeanFactory#getBean(java.lang.String)調用的是AbstractBeanFactory#doGetBean,下面來看該方法:
假設我們要獲取的bean是單例并且是首次獲取,那么真正創建bean是調用的312行的createBean方法。至此,我們來看一下整個方法鏈:
下面來看下AbstractAutowireCapableBeanFactory#initializeBean:
其中紅線框起來的四個方法分別是:
invokeAwareMethods:調用BeanNameAware.setBeanName, BeanFactoryAware.setBeanFactory等
applyBeanPostProcessorsBeforeInitialization:調用BeanPostProcessor.postProcessBeforeInitialization
invokeInitMethods:調用InitializingBean#afterPropertiesSet,調用自定義initMethod
applyBeanPostProcessorsAfterInitialization:調用BeanPostProcessor#postProcessAfterInitialization
之前提到在解析aop配置時向容器注冊了AspectJAwareAdvisorAutoProxyCreator,那么此處這個類要派上用場了。我們先來看下這個類的繼承體系:
從頂層看,該類主要包含三部分:
ProxyConfig即解析而來的aop配置
Aware部分主要是使其可訪問ClassLoader和BeanFactory
BeanPostProcessor則是bean初始化的前置和后置
上面出現的applyBeanPostProcessorsAfterInitialization調用的就是AspectJAwareAdvisorAutoProxyCreator的postProcessAfterInitialization,準確地說是其繼承自父類的父類
AbstractAutoProxyCreator.postProcessAfterInitialization。我們來看下該方法調用的
AbstractAutoProxyCreator#wrapIfNecessary,這也是spring判斷是否需要創建代理對象的地方:
該方法主要分三步:
352行判斷該接口或類或方法是否與配置的pointcut的表達式匹配,匹配則需要創建代理對象,不匹配則無需代理。然后如果匹配則返回方法攔截器
355行創建代理對象
357行對代理類進行緩存
我們重點看下createProxy方法實現,方法鏈如下:
有了方法鏈之后我們直接跳到DefaultAopProxyFactory#createAopProxy,這個方法決定了spring aop動態代理是使用CGLIB還是JDK Proxy:
解釋下51行if語句中的三個條件:
isOptimize表示讓spring自行優化,默認為false
isProxyTargetClass表示是否對類生成代理,默認為false(即使用JDK Proxy,只代理接口)
第三個表示bean沒有實現任何接口或者實現的接口是SpringProxy接口
綜上,spring AOP默認的創建代理的策略是:
對接口生成代理使用JDK Proxy
對類生成代理使用CGLIB
可通過proxyTargetClass配置是否對類生成代理,為true表示對類生成代理,為false表示不會對類(沒有實現SpringProxy以外的接口的類)生成代理
如果覺得寫的不錯,記得,如果寫的不好歡迎批評指正,讓我們一起進步!
轉載于:https://www.cnblogs.com/handsome1013/p/11572845.html
總結
以上是生活随笔為你收集整理的轻轻松松看懂Spring AOP源码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 算法题解:旋转数组的最小数字
- 下一篇: SpringBoot 参数符号转义,用这