上一篇文章我們從XML 配置文件的方式剖析了AOP的源碼,我們也說了,雖然現(xiàn)在用XML配置的幾乎沒有了,但作為學(xué)習(xí)的例子,XML配置仍然是我們理解Spring AOP 的一個絕好的樣本,但作為一個由追求的程序員,我們天天使用的注解方式的AOP 肯定也是要去看看到底是如何實現(xiàn)的?,F(xiàn)在有了之前閱讀 XML 配置的源碼的基礎(chǔ),今天我們來閱讀注解方式的源碼也變得輕松起來。
還記得我們之前說過,XML 配置的AOP是使用 ProxyFactoryBean ,實現(xiàn)了 FactoryBean的接口,而FactoryBean是Spring特意留給開發(fā)者們擴(kuò)展的接口,而Spring 留給開發(fā)者們不止一個擴(kuò)展接口,比如 BeanPostProcess 接口,實現(xiàn)著接口就可以在每個Bean的生成前后做一些增強或自定義(具體Spring 留給我們有哪些擴(kuò)展接口,樓主有機會將會再寫一篇文章解析)。
接下來就要好好講講我們上篇文章漏講的接口設(shè)計。這是我們理解 AOP 的基礎(chǔ)。
先從 ProxyFactoryBean 講起,這個熟悉的哥們。
1. ProxyFactoryBean 類結(jié)構(gòu)

1.1 ProxyCreatorSupport 類結(jié)構(gòu)圖
它繼承了 ProxyCreatorSupport 這個類,這個類很重要,我們看看該類結(jié)構(gòu)

該類有2個重要的方法,分別是獲取代理工廠,創(chuàng)建代理。那么代理工廠是什么呢?AopProxyFactory ,是個接口,只定義了一個方法:AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException, 并且該接口目前只有一個默認(rèn)實現(xiàn)類:DefaultAopProxyFactory,該類主要重寫了接口方法 createAopProxy, 內(nèi)部邏輯是根據(jù)給定的類配置來創(chuàng)建不同的代理 AopProxy,那么 AopProxy 是什么呢?就是真正創(chuàng)建代理的工廠,他是一個接口,有3個實現(xiàn):
1.2 AopProxy 接口

1.3 AopProxy 繼承結(jié)構(gòu)

從名字上可以看出來,一個是 JDK 動態(tài)代理,一個是 Cglib 代理,ObjenesisCglibAopProxy 擴(kuò)展了它的父類 CglibAopProxy,在 DefaultAopProxyFactory 的實現(xiàn)里,使用的就是 ObjenesisCglibAopProxy 來實現(xiàn) Cglib 的代理。他們分別實現(xiàn)了自己的getProxy 方法用以創(chuàng)建代理。我們看看這兩個類的繼承結(jié)構(gòu):
1.4 JdkDynamicAopProxy 繼承結(jié)構(gòu)

1.5 CglibAopProxy 繼承結(jié)構(gòu)沒什么,主要是眾多內(nèi)部類

可以看到喲非常多的內(nèi)部類,這些內(nèi)部類是為了實現(xiàn)了 Cglib 的各種回調(diào)而實現(xiàn)的。主要實現(xiàn)了 MethodInterceptor 接口,
Callback 接口,Joinpoint 接口,Invocation 接口等待,總之是實現(xiàn)了Spring 的 cglib 模塊的各種接口。
說了那么多,我們回來看看 ProxyCreatorSupport ,下面是 ProxyCreatorSupport 的繼承結(jié)構(gòu)
2. ProxyCreatorSupport 類繼承圖

該類有3個子類, 其中就有一個我們熟悉的 ProxyFactoryBean,該類實現(xiàn)了我們熟悉的 FactoryBean,還有一個可以獲取容器內(nèi)Bean的 BeanFactoyAware 接口,第二個是陌生的 AspectJProxyFactory 類,該類是用于集成 Spring 和 AspectJ 的。而最后一個類ProxyFactory 就是我們今天的主角,Spring 的類注釋說:用于編程使用的AOP代理,而不是在bean工廠中通過聲明式設(shè)置。這個類提供了一種簡單的方法,可以在定制的用戶代碼中獲取和配置AOP代理實例,大概意思就是通過編程的方式獲取Bean 代理吧,而不是通過配置文件的方式。我們今天就可以見識到。
3. AnnotationAwareAspectJAutoProxyCreator 類
這個類的名字很長,為什么要說這個類呢?還記得我們剛開始說的 BeanPostProcessor 擴(kuò)展接口嗎?我們說該接口是spring 留給開發(fā)人員自定義增強bean的接口。而該類則實現(xiàn)了該接口,看名字也知道,該類是根據(jù)注解自動創(chuàng)建代理的創(chuàng)建者類。我們看看他的類圖:

可以看到,最底層的該類實現(xiàn)了 BeanPostProcessor 接口,可以在每個bena生成前后做操作。該類由 Rod Johnson 編寫,注釋上是這么說的:任何AspectJ注釋的類都將自動被識別,它們也會被識別。和我們預(yù)想的一致。
我們知道了 AnnotationAwareAspectJAutoProxyCreator 是根據(jù)注解自動創(chuàng)建代理,而該類也算是 ProxyBean 的代理,那么,和它一樣繼承抽象父類的其他幾個類的作用是什么呢?來都來了,就看看吧!我們看看類圖:

可以看到該類由4個實現(xiàn):他們實現(xiàn)了不同的創(chuàng)建代理的方式:
- 匹配Bean的名稱自動創(chuàng)建匹配到的Bean的代理,實現(xiàn)類BeanNameAutoProxyCreator
- 根據(jù)Bean中的AspectJ注解自動創(chuàng)建代理,實現(xiàn)類AnnotationAwareAspectJAutoProxyCreator,也就是我們今天說的注解類。
- 根據(jù)Advisor的匹配機制自動創(chuàng)建代理,會對容器中所有的Advisor進(jìn)行掃描,自動將這些切面應(yīng)用到匹配的Bean中,實現(xiàn)類DefaultAdvisorAutoProxyCreator
- InfrastructureAdvisorAutoProxyCreator,該類只在 AopConfigUtils 中的靜態(tài)塊用到,該類的注釋:自動代理創(chuàng)建者只考慮基礎(chǔ)設(shè)施顧問bean,忽略任何應(yīng)用程序定義的顧問。意思應(yīng)該是只是Sprnig的基礎(chǔ)代理,開發(fā)者的應(yīng)用會忽略。有知道的同學(xué)可以告訴我。
加上我們的ProxyFactoryBean,一共5種實現(xiàn)方法。從這里可以看出Spring 對于擴(kuò)展的軟件設(shè)計是多么優(yōu)秀。
那么我們就來看看 AnnotationAwareAspectJAutoProxyCreator 是如何創(chuàng)建代理的。我們說 BeanPostProcessor 是Spring 留給我們擴(kuò)展的接口,那么他是如何定義的呢?我們看看該接口:
public interface BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
該接口定義了兩個方法,一個是在bean初始化之前執(zhí)行,一個是在bean初始化之后執(zhí)行。也就是說,開發(fā)者可以在這兩個方法中做一些有趣的事情。我們看看 AnnotationAwareAspectJAutoProxyCreator 是如何實現(xiàn)該方法的。實際上 AnnotationAwareAspectJAutoProxyCreator 的抽象父類已經(jīng)實現(xiàn)了該方法,我們看看是如何實現(xiàn)的:
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
before 方法直接返回了bean,并沒有做什么增強操作,重點在after方法,我們可以看該方法的注釋:如果bean是由子類標(biāo)識的,那么就創(chuàng)建一個配置的攔截器的代理。Spring 就是在這里創(chuàng)建了代理,我們進(jìn)入關(guān)鍵方法 wrapIfNecessary 看看。該方法用來包裝給定的Bean。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
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;
}
我們已將可以看到一個關(guān)鍵一行代碼:Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)),創(chuàng)建一個代理,該方法攜帶了bean的Class對象,benaName, 通知器數(shù)組,還有一個包裝過的單例Bean,我們看看該方法實現(xiàn)(該方法對于我們來說已經(jīng)到終點了),
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
我們能夠看到其中有一行讓我們激動的代碼,就是 ProxyFactory proxyFactory = new ProxyFactory(),創(chuàng)建了一個ProxyFactory 對象,我們剛剛說過,該對象和ProxyFactoryBean一樣,繼承了 ProxyCreatorSupport, 因此也就和 ProxyFactoryBean 一樣擁有了 getProxy 方法,到這里,我們的一切都豁然開朗。當(dāng)然上面幾行代碼是設(shè)置了通知器鏈。我們先按下不表。
ProxyFactoryBean 擴(kuò)展了 FactoryBean 接口, AnnotationAwareAspectJAutoProxyCreator 擴(kuò)展了 BenaPostProcessor 了接口,其目的都是在Bean生成的時候做增強操作,Spring 通過這兩種方式,完成了兩種不同的代理生成方式,但最終都是繼承了 ProxyCreatorSupport 類,該類才是生成代理的核心類。
我們可以看看XML 配置方式和 注解方式的方法堆棧調(diào)用圖,從中我們可以看出一些端倪:
XML 配置方式堆棧圖

注解配置方法堆棧圖

我們可以看到兩者在AbstractBeanFactory 的 doGetBean 方法開始分道揚鑣,走向了不同的邏輯,那么我們看看到底哪里不同,直接看代碼:我們看XML配置堆棧,在258行:

從這里進(jìn)入,該方法做了些什么呢?為什么讓他們走向不同的路線?我們看看該方法:

該方法有個重要的判斷:是否是 FactoryBean 的子類型,很明顯,我們的XML配置的ProxyFacoroyBean 返回 false,而注解方式的Bean則返回 false,ProxyFacoroyBean 會一直向下走,直到創(chuàng)建代理,而注解方式則會直接返回。走到302行:

注解方式會執(zhí)行 getSingleton 方法,最后觸發(fā) createBean 回調(diào)方法,完成創(chuàng)建代理的過程。
到此為止,現(xiàn)在我們知道了到 XML 配置方式的 AOP 和注解的方式AOP 的生成區(qū)別。我們可以開始總結(jié)了。
4. 總結(jié)
首先,通過分析源碼我們知道注解方式和 XML 配置方式的底層實現(xiàn)都是一樣的,都是通過繼承 ProxyCreatorSupport 來實現(xiàn)的,不同的通過擴(kuò)展不同的 Spring 提供的接口,XML 擴(kuò)展的是FactoryBean 接口, 而注解方式擴(kuò)展的是 BenaPostProcessor 接口,通過Spring 的擴(kuò)展接口,能夠?qū)μ囟ǖ腂ean進(jìn)行增強。而 AOP 正式通過這種方式實現(xiàn)的。這也提醒了我們,我們也可以通過擴(kuò)展 Spring 的某些接口來增強我們需要的 Bean 的某些功能。當(dāng)然,篇幅有限,我們這篇文章只是了解了XML 配置方式和注解方式創(chuàng)建代理的區(qū)別,關(guān)于如何 @Aspect 和 @Around 的底層實現(xiàn),還有通知器的底層實現(xiàn),我們還沒有分析,但我們隱隱的感覺到,其實萬變不離其宗,底層的也是通過擴(kuò)展 advice 和 pointcut 接口來實現(xiàn)的。 我們將會在后面的文章繼續(xù)分析 AOP 是如何編織通知的。
good luck ?。。。?/p>