前言
最近看了《從零開(kāi)始寫(xiě)JavaWeb框架》茁肠,想比較一下Spring AOP的實(shí)現(xiàn)方式和書(shū)的上實(shí)現(xiàn)方式有什么不同遭顶,所以先把Spring AOP的源碼讀一下瞒爬,再進(jìn)行比較瘾带。
Spring的源碼實(shí)在是復(fù)雜,在讀的過(guò)程中參考了很多書(shū)和網(wǎng)上的文章驻售,本文算是這些文章的總結(jié)露久,再加上一些我自己對(duì)另個(gè)細(xì)節(jié)的理解。
本文分成 3 部分:
- 程序入口
- 切面和增強(qiáng)的取得
- 代理的生成
一欺栗,注冊(cè)AspectJAnnotationAutoProxyCreator
如果使用<aop:aspectj-autoproxy />
標(biāo)簽來(lái)自動(dòng)生成代理的話毫痕,入口程序是AopNamespaceHandler
征峦。在AopNamespaceHandler
中,下面一段代碼是對(duì)<aop:aspectj-autoproxy />
標(biāo)簽執(zhí)行的調(diào)用:
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
AspectJAutoProxyBeanDefinitionParser解析器中消请,首先調(diào)用的parse方法栏笆。parse方法中有一行代碼:
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
我們看一下registerAspectJAnnotationAutoProxyCreatorIfNecessary
方法的實(shí)際內(nèi)容:
public static void registerAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 注冊(cè)或更新 AutoProxyCreator 定義 beanName 為 org.Springframework.aop.config.internalAutoProxyCreator的BeanDefinition
// 如果internalAutoProxyCreator的BeanDefinition已經(jīng)存在,而根據(jù)優(yōu)先級(jí)更新BeanDefinition
// 在這里我們注冊(cè)的是AnnotationAwareAspectJAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 對(duì)于 proxy-target-class 以及 expose-proxy 屬性的處理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 注冊(cè)組件并通知梯啤,便于監(jiān)聽(tīng)器作進(jìn)一步處理
// 其中 beanDefinition 的 className 為 AnnotationAwareAspectJAutoProxyCreator
registerComponentIfNecessary(beanDefinition, parserContext);
}
那為什么注冊(cè)AnnotationAwareAspectJAutoProxyCreator竖伯,注冊(cè)AnnotationAwareAspectJAutoProxyCreator有什么用呢?
其實(shí),實(shí)現(xiàn)AOP處理是其實(shí)是通過(guò)BeanPostProcessor機(jī)制實(shí)現(xiàn)的因宇。AnnotationAwareAspectJAutoProxyCreator的父類(lèi)也實(shí)現(xiàn)一個(gè)BeanPostProcessor類(lèi)型的接口七婴,而生成代理的邏輯就在AnnotationAwareAspectJAutoProxyCreator的BeanPostProcessor接口實(shí)現(xiàn)里面。
更嚴(yán)謹(jǐn)?shù)卣f(shuō)察滑,AnnotationAwareAspectJAutoProxyCreator
的父類(lèi)實(shí)現(xiàn)的接口是
SmartInstantiationAwareBeanPostProcessor
打厘,主要是Spring框架內(nèi)部使用的一個(gè)接口。而這個(gè)接口的父接口InstantiationAwareBeanPostProcessor
是實(shí)現(xiàn)代理的重點(diǎn)之一贺辰。
這3個(gè)接口的關(guān)系如下:
SmartInstantiationAwareBeanPostProcessor -> InstantiationAwareBeanPostProcessor -> BeanPostProcessor
為什么說(shuō)是是InstantiationAwareBeanPostProcessor
接口的子接口户盯,接口是重點(diǎn)之一?那InstantiationAwareBeanPostProcessor
接口是什么接口呢饲化?
BeanPostProcessor
主要作用于Bean
實(shí)例化后莽鸭,初始化前后。InstantiationAwareBeanPostProcessor
雖然是BeanPostProcessor
的子接口吃靠,但它的調(diào)用時(shí)間點(diǎn)其發(fā)生在Bean實(shí)例化前硫眨,在真正調(diào)用doCreate()
創(chuàng)建bean實(shí)例之前。
在創(chuàng)建Bean
實(shí)例之前巢块,會(huì)先調(diào)用resolveBeforeInstantiation
方法礁阁,這個(gè)方法是生成Bean
代理的地方。如果此方法返回值不為空則直接返回生成的Bean
的代理族奢,如果為空就向下走正常的Bean
生成流程姥闭。
spring注釋“Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. ”給BeanPostProcessors一個(gè)機(jī)會(huì)返回代理proxy對(duì)象。
而InstantiationAwareBeanPostProcessor
接口方法越走,就是在resolveBeforeInstantiation
方法中調(diào)用的棚品。所以可以看出,BeanPostProcessore
有很多廊敌,但Spring AOP的實(shí)現(xiàn)就是通過(guò)InstantiationAwareBeanPostProcessor
這個(gè)BeanPostProcessor
實(shí)現(xiàn)的南片。看一下源碼:
protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
......
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 如果返回值不為空庭敦,說(shuō)明生成成了此BeanName的代理,直接返回代理對(duì)象
Object bean = resolveBeforeInstantiation(beanName, mbd);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
......
}
// 如果沒(méi)有生成代理對(duì)象薪缆,就按正常流程走秧廉,生成Bean對(duì)象
Object beanInstance = doCreateBean(beanName, mbd, args);
.....
return beanInstance;
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 調(diào)用InstantiationAwareBeanPostProcessor接口的地方
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
throws BeansException {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
// 轉(zhuǎn)換成InstantiationAwareBeanPostProcessor接口伞广,并調(diào)用
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
順帶說(shuō)一下,注冊(cè)AnnotationAwareAspectJAutoProxyCreator的目的是:把這個(gè)類(lèi)的BeanDefinition通過(guò)registerBeanDefinition方法(DefaultListableBeanFactory類(lèi)中)加入到beanDefinitionMap中疼电,作為一個(gè)Bean讓Spring管理嚼锄,這樣Spring就可以隨意取得它了。
如果使用<aop:aspectj-autoproxy />
標(biāo)簽來(lái)自動(dòng)生成代理的話蔽豺,入口程序是AopNamespaceHandler
区丑。那AopNamespaceHandler
是在什么地方被調(diào)用的呢?
這個(gè)問(wèn)題讓我們從容器啟動(dòng)的地方開(kāi)始說(shuō)明修陡。以FileSystemXmlApplicationContext
為例沧侥,這個(gè)類(lèi)的入口是構(gòu)造函數(shù)里面的refresh()
方法。從refresh()
方法開(kāi)始魄鸦,調(diào)用流程是這樣的:(以下流程全部是嵌套調(diào)用的關(guān)系)
1. refresh() ->
刷新容器
2. obtainFreshBeanFactory() ->
獲得刷新后的Bean容器
3. refreshBeanFactory() ->
刷新Bean容器
4. loadBeanDefinitions() ->
加載BeanDefinition
5. XmlBeanDefinitionReader#loadBeanDefinitions
新建一個(gè)XmlBeanDefinitionReader實(shí)例(new XmlBeanDefinitionReader(beanFactory))宴杀,調(diào)用這個(gè)實(shí)例的loadBeanDefinitions方法。
6. XmlBeanDefinitionReader#doLoadBeanDefinitions
7. XmlBeanDefinitionReader#registerBeanDefinitions
8. XmlBeanDefinitionReader#createBeanDefinitionDocumentReader
在這個(gè)方法中取得了DefaultBeanDefinitionDocumentReader實(shí)例拾因。接下來(lái)調(diào)用這個(gè)實(shí)例的方法旺罢。
9. DefaultBeanDefinitionDocumentReader#registerBeanDefinitions
在這個(gè)方法中,根據(jù)URI判斷是否使用AopNamespaceHandler
10. DefaultBeanDefinitionDocumentReader#parseBeanDefinitions
從registerBeanDefinitions方法開(kāi)始绢记,內(nèi)部連續(xù)調(diào)用一系列方法扁达,一直調(diào)用到parseBeanDefinitions方法。在這個(gè)方法中蠢熄,根據(jù)XML文件的URI判斷使用哪些解析器跪解,例如是<Beans>類(lèi)標(biāo)簽解析器,還是<aop>類(lèi)標(biāo)簽解析器护赊。
如果是需要<aop>標(biāo)簽解析器的話惠遏,在this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri)代碼中,從配置文件(spring.handlers)從取出AopNamespaceHandler的類(lèi)名骏啰,生成這個(gè)類(lèi)的實(shí)例节吮,然后調(diào)用這個(gè)類(lèi)的parse方法。
11. AopNamespaceHandler#parse
這個(gè)方法的功能是判耕,根據(jù)具體標(biāo)簽調(diào)用具體解析器的parse方法透绩。
- <aop:aspectj-autoproxy>:AspectJAutoProxyBeanDefinitionParser
- <aop:config>:ConfigBeanDefinitionParser
等。
這個(gè)方法的調(diào)用壁熄,又回到了我們最初講的AopNamespaceHandler入口的地方帚豪。
到此為止,從容器到AopNamespaceHandler類(lèi)調(diào)用的過(guò)程也講完了草丧。
二狸臣,AspectJAnnotationAutoProxyCreator的流程
通過(guò)上面的內(nèi)容,我們知道了注冊(cè)AnnotationAwareAspectJAutoProxyCreator
的意義昌执,并且知道了生成代理是在它的BeanPostProcessor
接口里做的烛亦,現(xiàn)在看看被實(shí)現(xiàn)的接口的內(nèi)容诈泼。(postProcessAfterInitialization 具體實(shí)現(xiàn)是在其父類(lèi) AbstractAutoProxyCreator 中完成的):
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
// 根據(jù)給定的 bean 的 class 和 name 構(gòu)建出個(gè) key,格式:beanClassName_beanName
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 如果它適合被代理煤禽,則需要封裝指定 bean铐达。
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 是否已經(jīng)處理過(guò)
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 無(wú)需增強(qiáng)
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 給定的 bean 類(lèi)是否代表一個(gè)基礎(chǔ)設(shè)施類(lèi),基礎(chǔ)設(shè)施類(lèi)不應(yīng)代理檬果,或者配置了指定 bean 不需要自動(dòng)代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 如果存在增強(qiáng)方法則創(chuàng)建代理(*重要*)
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果獲取到了增強(qiáng)則需要針對(duì)增強(qiáng)創(chuàng)建代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 創(chuàng)建代理(*重要*)
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
這里有兩個(gè)方法特別重要:
- getAdvicesAndAdvisorsForBean:如果Bean是要被代理的對(duì)象的話瓮孙,取得Bean相關(guān)的Interceptor
- createProxy:創(chuàng)建代理
下一篇文章,我們就這兩個(gè)方法的下面的流程分開(kāi)來(lái)分析一下选脊,首先分析getAdvicesAndAdvisorsForBean
相關(guān)代碼杭抠。
關(guān)于接口實(shí)現(xiàn)的補(bǔ)充:
AnnotationAwareAspectJAutoProxyCreator
一共實(shí)現(xiàn)了2個(gè)BeanPostProcessor
的接口,的4個(gè)方法:
- postProcessBeforeInstantiation(InstantiationAwareBeanPostProcessor)
- postProcessAfterInstantiation(InstantiationAwareBeanPostProcessor)
- postProcessBeforeInitialization(BeanPostProcessor)
- postProcessAfterInitialization(BeanPostProcessor)
postProcessBeforeInstantiation
(InstantiationAwareBeanPostProcessor
接口)方法中知牌,這個(gè)方法是在AnnotationAwareAspectJAutoProxyCreator
的基類(lèi)AbstractAutoProxyCreator
中實(shí)現(xiàn)的祈争。細(xì)看一下,在postProcessAfterInitialization
方法中也有類(lèi)似的生成代理的代碼角寸。這是為什么呢菩混?
上網(wǎng)找了一些資料,在postProcessBeforeInstantiation
方法中有一個(gè)判斷:
如果某個(gè)
Bean
設(shè)置了自定義TargetSource
的話扁藕,就在本方法中進(jìn)行生成代理而
postProcessAfterInitialization
則沒(méi)有這樣的判斷沮峡,只是在生成代理前判斷了一下代理是否已經(jīng)生成。具體為什么有這樣的必須還不清楚(以后有需要調(diào)查一下)亿柑,但結(jié)果就是:
- 如果
Bean
設(shè)置了自定義TargetSource
邢疙,就在postProcessBeforeInstantiation
中生成代理 - 如果沒(méi)有,就在
postProcessAfterInitialization
中生成代理望薄。
最后疟游,不管理在哪個(gè)方法里生成代理,在創(chuàng)建每個(gè)Bean時(shí)都會(huì)被調(diào)用這兩個(gè)方法痕支,代理的生成邏輯就是在這兩個(gè)方法中實(shí)現(xiàn)的颁虐。
關(guān)于TargetSource:spring-aop組件詳解——TargetSource目標(biāo)源
關(guān)于自定義TargetSource:《Spring揭密》的9.6章節(jié)