- Spring技術(shù)內(nèi)幕:深入解析Spring架構(gòu)與設(shè)計(jì)原理(第2版)
- 計(jì)文柯
- 5909字
- 2018-12-31 19:55:44
3.3 建立AopProxy代理對象
3.3.1 設(shè)計(jì)原理
在Spring的AOP模塊中,一個(gè)主要的部分是代理對象的生成,而對于Spring應(yīng)用,可以看到,是通過配置和調(diào)用Spring的ProxyFactoryBean來完成這個(gè)任務(wù)的。在ProxyFactoryBean中,封裝了主要代理對象的生成過程。在這個(gè)生成過程中,可以使用JDK的Proxy和CGLIB兩種生成方式。
以ProxyFactory的設(shè)計(jì)為中心,可以看到相關(guān)的類繼承關(guān)系如圖3-11所示。

圖3-11 類繼承關(guān)系
在這個(gè)類繼承關(guān)系中,可以看到完成AOP應(yīng)用的類,比如AspectJProxyFactory、ProxyFactory和ProxyFactoryBean,它們都在同一個(gè)類的繼承體系下,都是ProxyConfig、AdvisedSupport和ProxyCreatorSupport的子類。作為共同基類,可以將ProxyConfig看成是一個(gè)數(shù)據(jù)基類,這個(gè)數(shù)據(jù)基類為ProxyFactoryBean這樣的子類提供了配置屬性;在另一個(gè)基類AdvisedSupport的實(shí)現(xiàn)中,封裝了AOP對通知和通知器的相關(guān)操作,這些操作對于不同的AOP的代理對象的生成都是一樣的,但對于具體的AOP代理對象的創(chuàng)建,AdvisedSupport把它交給它的子類們?nèi)ネ瓿桑粚τ赑roxyCreatorSupport,可以將它看成是其子類創(chuàng)建AOP代理對象的一個(gè)輔助類。通過繼承以上提到的基類的功能實(shí)現(xiàn),具體的AOP代理對象的生成,根據(jù)不同的需要,分別由ProxyFactoryBean、AspectJProxyFactory和ProxyFactory來完成。對于需要使用AspectJ的AOP應(yīng)用,AspectJProxyFactory起到集成Spring和AspectJ的作用;對于使用Spring AOP的應(yīng)用,ProxyFactoryBean和ProxyFactoy都提供了AOP功能的封裝,只是使用ProxyFactoryBean,可以在IoC容器中完成聲明式配置,而使用ProxyFactory,則需要編程式地使用Spring AOP的功能;對于它們是如何封裝實(shí)現(xiàn)AOP功能的,會在本章小結(jié)中給出詳細(xì)的分析,在這里,通過這些類層次關(guān)系的介紹,先給讀者留下一個(gè)大致的印象。Proxy-FactoryBean相關(guān)的類層次關(guān)系如圖3-12所示。

圖3-12 ProxyFactoryBean相關(guān)的類層次關(guān)系
關(guān)于AOP的實(shí)現(xiàn)過程,在了解其設(shè)計(jì)原理之后,下面詳細(xì)分析從配置ProxyFactoryBean開始到具體的代理對象生成。
3.3.2 配置ProxyFactoryBean
從這部分開始,進(jìn)入到Spring AOP的實(shí)現(xiàn)部分,在分析Spring AOP的實(shí)現(xiàn)原理中,主要以ProxyFactoryBean的實(shí)現(xiàn)作為例子和實(shí)現(xiàn)的基本線索進(jìn)行分析。這是因?yàn)镻roxyFactoryBean是在Spring IoC環(huán)境中創(chuàng)建AOP應(yīng)用的底層方法,也是最靈活的方法,Spring通過它完成了對AOP使用的封裝。以ProxyFactoryBean的實(shí)現(xiàn)為入口,逐層深入,是一條幫助我們快速理解Spring AOP實(shí)現(xiàn)的學(xué)習(xí)路徑。
在了解ProxyFactoryBean的實(shí)現(xiàn)之前,先簡要介紹一下ProxyFactoryBean的配置和使用,在基于XML配置Spring的Bean時(shí),往往需要一系列的配置步驟來使用ProxyFactoryBean和AOP。
1)定義使用的通知器Advisor,這個(gè)通知器應(yīng)該作為一個(gè)Bean來定義。很重要的一點(diǎn)是,這個(gè)通知器的實(shí)現(xiàn)定義了需要對目標(biāo)對象進(jìn)行增強(qiáng)的切面行為,也就是Advice通知。
2)定義ProxyFactoryBean,把它作為另一個(gè)Bean來定義,它是封裝AOP功能的主要類。在配置ProxyFactoryBean時(shí),需要設(shè)定與AOP實(shí)現(xiàn)相關(guān)的重要屬性,比如proxyInterface、interceptorNames和target等。從屬性名稱可以看出,interceptorNames屬性的值往往設(shè)置為需要定義的通知器,因?yàn)檫@些通知器在ProxyFactoryBean的AOP配置下,是通過使用代理對象的攔截器機(jī)制起作用的。所以,這里依然沿用了攔截器這個(gè)名字,也算是舊瓶裝新酒吧。
3)定義target屬性,作為target屬性注入的Bean,是需要用AOP通知器中的切面應(yīng)用來增強(qiáng)的對象,也就是前面提到的base對象。
有了這些配置,就可以使用ProxyFactoryBean完成AOP的基本功能了。關(guān)于配置的例子,如代碼清單3-10所示。與前面提到的配置步驟相對應(yīng),可以看到,除定義了ProxyFactoryBean的AOP封裝外,還定義了一個(gè)Advisor,名為testAdvisor。作為ProxyFactory配置的一部分,還需要配置攔截的方法調(diào)用接口和目標(biāo)對象。這些基本的配置,是使用ProxyFactoryBean實(shí)現(xiàn)AOP功能的重要組成,其實(shí)現(xiàn)和作用機(jī)制也是后面重點(diǎn)分析的內(nèi)容。
代碼清單3-10 配置ProxyFactoryBean
<bean id="testAdvisor" class="com.abc.TestAdvisor"/> <bean id="testAOP" class="org.springframework.aop.ProxyFactoryBean> <property name="proxyInterfaces"><value>com.test.AbcInterface"</value></property> <property name="target"> <bean class="com.abc.TestTarget"/> </property> <property name="interceptorNames"> <list><value> testAdvisor</value></list> </property> </bean>
掌握這些配置后,就可以具體看一看這些AOP是如何實(shí)現(xiàn)的,也就是說,切面應(yīng)用是怎樣通過ProxyFactoryBean對target對象起作用的,下面我們會詳細(xì)地分析這個(gè)部分。
3.3.3 ProxyFactoryBean生成AopProxy代理對象
在Spring AOP的使用中,我們已經(jīng)了解到,可以通過ProxyFactoryBean來配置目標(biāo)對象和切面行為。這個(gè)ProxyFactoryBean是一個(gè)FactoryBean,對FactoryBean這種Spring應(yīng)用中經(jīng)常出現(xiàn)的Bean的工作形式,大家一定不會感到陌生, 對于FactoryBean的工作原理,已經(jīng)在結(jié)合IoC容器的實(shí)現(xiàn)原理分析中做過闡述。在ProxyFactoryBean中,通過interceptorNames屬性來配置已經(jīng)定義好的通知器Advisor。雖然名字為interceptorNames,但實(shí)際上卻是供AOP應(yīng)用配置通知器的地方。在ProxyFactoryBean中,需要為target目標(biāo)對象生成Proxy代理對象,從而為AOP橫切面的編織做好準(zhǔn)備工作。這些具體的代理對象生成工作,在以后的實(shí)現(xiàn)原理分析中,我們可以看到是通過JDK的Proxy或CGLIB來完成的。具體的AopProxy生成過程如圖3-13所示。

圖3-13 AopProxy的生成過程
ProxyFactoryBean的AOP實(shí)現(xiàn)需要依賴JDK或者CGLIB提供的Proxy特性。從FactoryBean中獲取對象,是以getObject()方法作為入口完成的;ProxyFactoryBean實(shí)現(xiàn)中的getObject方法,是FactoryBean需要實(shí)現(xiàn)的接口。對ProxyFactoryBean來說,把需要對target目標(biāo)對象增加的增強(qiáng)處理,都通過getObject方法進(jìn)行封裝了,這些增強(qiáng)處理是為AOP功能的實(shí)現(xiàn)提供服務(wù)的。getObject的實(shí)現(xiàn)如代碼清單3-11所示。getObject方法首先對通知器鏈進(jìn)行初始化,通知器鏈封裝了一系列的攔截器,這些攔截器都要從配置中讀取,然后為代理對象的生成做好準(zhǔn)備。在生成代理對象時(shí),因?yàn)镾pring中有singleton類型和prototype類型這兩種不同的Bean,所以要對代理對象的生成做一個(gè)區(qū)分。
代碼清單3-11 ProxyFactoryBean的getObject
public Object getObject() throws BeansException { //這里初始化通知器鏈 initializeAdvisorChain(); //這里對singleton和prototype的類型進(jìn)行區(qū)分,生成對應(yīng)的proxy if (isSingleton()) { return getSingletonInstance(); } else { if (this.targetName == null) { logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +"Enable prototype proxies by setting the 'targetName' property."); } return newPrototypeInstance(); } }
為Proxy代理對象配置Advisor鏈?zhǔn)窃趇nitializeAdvisorChain方法中完成的,如代碼清單3-12所示。這個(gè)初始化過程有一個(gè)標(biāo)志位advisorChainInitialized,這個(gè)標(biāo)志用來表示通知器鏈?zhǔn)欠褚呀?jīng)初始化。如果已經(jīng)初始化,那么這里就不會再初始化,而是直接返回。也就是說,這個(gè)初始化的工作發(fā)生在應(yīng)用第一次通過ProxyFactoryBean去獲取代理對象的時(shí)候。在完成這個(gè)初始化之后,接著會讀取配置中出現(xiàn)的所有通知器,這個(gè)取得通知器的過程也比較簡單,把通知器的名字交給容器的getBean方法就可以了,這是通過對IoC容器實(shí)現(xiàn)的一個(gè)回調(diào)來完成的。然后把從IoC容器中取得的通知器加入攔截器鏈中,這個(gè)動作是由addAdvisorOnChainCreation方法來實(shí)現(xiàn)的。
代碼清單3-12 對Advisor配置鏈的初始化
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException { if (this.advisorChainInitialized) { return; } if (!ObjectUtils.isEmpty(this.interceptorNames)) { if (this.beanFactory == null) { throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " + "- cannot resolve interceptor names " + Arrays.asList (this.interceptorNames)); } if (this.interceptorNames[this.interceptorNames.length -1]. endsWith(GLOBAL_SUFFIX) &&this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) { throw new AopConfigException("Target required after globals"); } // 這里是添加Advisor鏈的調(diào)用,是通過interceptorNames屬性進(jìn)行配置的 for (String name : this.interceptorNames) { if (logger.isTraceEnabled()) { logger.trace("Configuring advisor or advice '" + name + "'"); } if (name.endsWith(GLOBAL_SUFFIX)) { if (!(this.beanFactory instanceof ListableBeanFactory)) { throw new AopConfigException( "Can only use global advisors or interceptors with a ListableBeanFactory"); } addGlobalAdvisor((ListableBeanFactory) this.beanFactory, name.substring(0, name.length() - GLOBAL_SUFFIX.length())); } else { /* 如果程序在這里被調(diào)用,那么需要加入命名的攔截器advice,并且需要檢查這 個(gè)Bean是singleton還是prototype類型*/ Object advice; //如果是singleton類型Bean if (this.singleton || this.beanFactory.isSingleton(name)) { //加入advice或者advisor advice = this.beanFactory.getBean(name); } else { //對prototype類型Bean的處理 advice = new PrototypePlaceholderAdvisor(name); } addAdvisorOnChainCreation(advice, name); } } } this.advisorChainInitialized = true; }
生成singleton的代理對象在getSingletonInstance()的代碼中完成,這個(gè)方法是ProxyFactoryBean生成AopProxy代理對象的調(diào)用入口。代理對象會封裝對target目標(biāo)對象的調(diào)用,也就是說針對target對象的方法調(diào)用行為會被這里生成的代理對象所攔截。具體的生成過程是,首先讀取ProxyFactoryBean中的配置,為生成代理對象做好必要的準(zhǔn)備,比如設(shè)置代理的方法調(diào)用接口等。Spring通過AopProxy類來具體生成代理對象。對于getSingletonInstance()方法中代理對象的生成過程,如代碼清單3-13所示。
代碼清單3-13 生成單件代理對象
private synchronized Object getSingletonInstance() { if (this.singletonInstance == null) { this.targetSource = freshTargetSource(); if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) { //根據(jù)AOP框架來判斷需要代理的接口 Class targetClass = getTargetClass(); if (targetClass == null) { throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy"); } // 這里設(shè)置代理對象的接口 setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader)); } super.setFrozen(this.freezeProxy); // 注意這里的方法會使用ProxyFactory來生成需要的Proxy this.singletonInstance = getProxy(createAopProxy()); } return this.singletonInstance; } //通過createAopProxy返回的AopProxy來得到代理對象 protected Object getProxy(AopProxy aopProxy) { return aopProxy.getProxy(this.proxyClassLoader); }
這里出現(xiàn)了AopProxy類型的對象,Spring利用這個(gè)AopProxy接口類把AOP代理對象的實(shí)現(xiàn)與框架的其他部分有效地分離開來。AopProxy是一個(gè)接口,它由兩個(gè)子類實(shí)現(xiàn),一個(gè)是Cglib2AopProxy,另一個(gè)是JdkDynamicProxy。顧名思義,對這兩個(gè)AopProxy接口的子類的實(shí)現(xiàn),Spring分別通過CGLIB和JDK來生成需要的Proxy代理對象。
具體的代理對象的生成,是在ProxyFactoryBean的基類AdvisedSupport的實(shí)現(xiàn)中借助AopProxyFactory完成的,這個(gè)代理對象要么從JDK中生成,要么借助CGLIB獲得。因?yàn)镻roxyFactoryBean本身就是AdvisedSupport的子類,所以在ProxyFactoryBean中獲得AopProxy是很方便的,可以在ProxyCreatorSupport中看到,具體的AopProxy是通過AopProxyFactory來生成的。至于需要生成什么樣的代理對象,所有信息都封裝在AdvisedSupport里,這個(gè)對象也是生成AopProxy的方法的輸入?yún)?shù),這里設(shè)置為this本身,因?yàn)镻roxyCreatorSupport本身就是AdvisedSupport的子類。在ProxyCreatorSupport中生成代理對象的入口實(shí)現(xiàn),如代碼清單3-14所示。
代碼清單3-14 ProxyCreatorSupport生成AopProxy對象
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } //通過AopProxyFactory取得AopProxy,這個(gè)AopProxyFactory是在初始化函數(shù)中 //定義的,使用的是DefaultAopProxyFactory return getAopProxyFactory().createAopProxy(this); }
這里使用了AopProxyFactory來創(chuàng)建AopProxy,AopProxyFactory使用的是DefaultAopProxyFactory。這個(gè)被使用的AopProxyFactory,作為AopProxy的創(chuàng)建工廠對象,是在ProxyFactoryBean的基類ProxyCreatorSupport中被創(chuàng)建的。在創(chuàng)建AopProxyFactory時(shí),它被設(shè)置為DefaultAopProxyFactory,很顯然,Spring給出了這個(gè)默認(rèn)的AopProxyFactory工廠的實(shí)現(xiàn)。有了這個(gè)AopProxyFactory對象以后,問題就轉(zhuǎn)換為在DefaultAopProxyFactory中,AopProxy是怎樣生成的了。
關(guān)于AopProxy代理對象的生成,需要考慮使用哪種生成方式,如果目標(biāo)對象是接口類,那么適合使用JDK來生成代理對象,否則Spring會使用CGLIB來生成目標(biāo)對象的代理對象。為了滿足不同的代理對象生成的要求,DefaultAopProxyFactory作為AopProxy對象的生產(chǎn)工廠,可以根據(jù)不同的需要生成這兩種AopProxy對象。對于AopProxy對象的生產(chǎn)過程,在DefaultAopProxyFactory創(chuàng)建AopProxy的過程中可以清楚地看到,但這是一個(gè)比較高層次的AopProxy代理對象的生成過程,如代碼清單3-15所示。所謂高層次,是指在DefaultAopProxyFactory創(chuàng)建AopProxy的過程中,對不同的AopProxy代理對象的生成所涉及的生成策略和場景做了相應(yīng)的設(shè)計(jì),但是對于具體的AopProxy代理對象的生成,最終并沒有由DefaultAopProxyFactory來完成,比如對JDK和CGLIB這些具體的技術(shù)的使用,對具體的實(shí)現(xiàn)層次的代理對象的生成,是由Spring封裝的JdkDynamicAopProxy和CglibProxyFactory類來完成的。
代碼清單3-15 在DefaultAopProxyFactory中創(chuàng)建AopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() ||hasNoUserSupplied- ProxyInterfaces(config)) { Class targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); }//如果targetClass是接口類,使用JDK來生成Proxy if (targetClass.isInterface()) { return new JdkDynamicAopProxy(config); } if (!cglibAvailable) { throw new AopConfigException( "Cannot proxy target class because CGLIB2 is not available. " + "Add CGLIB to the class path or specify proxy interfaces."); } //如果不是接口類要生成Proxy,那么使用CGLIB來生成 return CglibProxyFactory.createCglibProxy(config); } else { return new JdkDynamicAopProxy(config); } }
在AopProxy代理對象的生成過程中,首先要從AdvisedSupport對象中取得配置的目標(biāo)對象,這個(gè)目標(biāo)對象是實(shí)現(xiàn)AOP功能所必需的,道理很簡單,AOP完成的是切面應(yīng)用對目標(biāo)對象的增強(qiáng),皮之不存,毛將焉附,這個(gè)目標(biāo)對象可以看做是“皮”,而AOP切面增強(qiáng)就是依附于這塊皮上的“毛”。如果這里沒有配置目標(biāo)對象,會直接拋出異常,提醒AOP應(yīng)用, 需要提供正確的目標(biāo)對象的配置。在對目標(biāo)對象配置的檢查完成以后,需要根據(jù)配置的情況來決定使用什么方式來創(chuàng)建AopProxy代理對象,一般而言,默認(rèn)的方式是使用JDK來產(chǎn)生AopProxy代理對象,但是如果遇到配置的目標(biāo)對象不是接口類的實(shí)現(xiàn),會使用CGLIB來產(chǎn)生AopProxy代理對象;在使用CGLIB來產(chǎn)生AopProxy代理對象時(shí),因?yàn)镃GLIB是一個(gè)第三方的類庫,本身不在JDK的基本類庫中,所以需要在CLASSPATH路徑中進(jìn)行正確的配置,以便能夠加載和使用。在Spring中,使用JDK和CGLIB來生成AopProxy代理對象的工作,是由JdkDynamicAopProxy和CglibProxyFactory來完成的。詳細(xì)的代理對象的生成過程會在下面的小節(jié)進(jìn)行詳細(xì)的分析。
3.3.4 JDK生成AopProxy代理對象
前面介紹的ProxyFactoryBean在AopProxy代理對象和IoC容器配置之間起到了橋梁的作用,這個(gè)橋梁作用體現(xiàn)在它為代理對象的最終生成做好了準(zhǔn)備。AopProxy代理對象可以由JDK或CGLIB來生成,而JdkDynamicAopProxy和Cglib2AopProxy實(shí)現(xiàn)的都是通過AopProxy接口,它們的層次關(guān)系如圖3-14所示。從源代碼實(shí)現(xiàn)中,也可以看到相對應(yīng)的接口實(shí)現(xiàn)關(guān)系。

圖3-14 AopProxy接口的層次關(guān)系
在這里可以看到使用兩種代理對象的實(shí)現(xiàn)方式,一種是使用CGLIB,另一種使用JDK自己的Proxy。具體怎樣生成代理對象,通過這兩個(gè)類的源代碼實(shí)現(xiàn)就可以了解,在AopProxy的接口下,設(shè)計(jì)了Cglib2AopProxy和JdkDynamicAopProxy兩種Proxy代理對象的實(shí)現(xiàn),而AopProxy的接口設(shè)計(jì)也很簡單,就是獲得Proxy代理對象。獲得Proxy代理對象的方式有兩種,一種方式是需要指定ClassLoader,另一種方式則不需要指定,如圖3-15所示。

圖3-15 AopProxy接口
先看看在AopProxy接口實(shí)現(xiàn)中,JdkDynamicAopProxy是怎樣完成AopProxy代理對象生成工作的,這個(gè)代理對象的生成過程如代碼清單3-16所示。在JdkDynamicAopProxy中,使用了JDK的Proxy類來生成代理對象,在生成Proxy對象之前,首先需要從advised對象中取得代理對象的代理接口配置,然后調(diào)用Proxy的newProxyInstance方法,最終得到對應(yīng)的Proxy代理對象。在生成代理對象時(shí),需要指明三個(gè)參數(shù),一個(gè)是類裝載器,一個(gè)是代理接口,另外一個(gè)就是Proxy回調(diào)方法所在的對象,這個(gè)對象需要實(shí)現(xiàn)InvocationHandler接口。這個(gè)InvocationHandler接口定義了invoke方法,提供代理對象的回調(diào)入口。對于JdkDynamicAopProxy,它本身實(shí)現(xiàn)了InvocationHandler接口和invoke方法,這個(gè)invoke方法是Proxy代理對象的回調(diào)方法,所以可以使用this來把JdkDynamicAopProxy指派給Proxy對象,也就是說JdkDynamicAopProxy對象本身,在Proxy代理的接口方法被調(diào)用時(shí),會觸發(fā)invoke方法的回調(diào),這個(gè)回調(diào)方法完成了AOP編織實(shí)現(xiàn)的封裝。在這里先重點(diǎn)關(guān)注AopProxy代理對象的生成,Proxy代理對象的invoke實(shí)現(xiàn),將是詳細(xì)分析AOP實(shí)現(xiàn)原理的重要部分。
代碼清單3-16 JdkDynamicAopProxy生成Proxy代理對象
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised. getTargetSource()); } Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces (this.advised); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); //這是調(diào)用JDK生成Proxy的地方 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); }
3.3.5 CGLIB生成AopProxy代理對象
在AopProxy接口實(shí)現(xiàn)中,可以看到使用CGLIB來生成Proxy代理對象,這個(gè)Proxy代理對象的生成可以在Cglib2AopProxy的代碼實(shí)現(xiàn)中看到,同樣是在AopProxy的接口方法getProxy的實(shí)現(xiàn)中完成的,如代碼清單3-17所示。
代碼清單3-17 Cglib2AopProxy生成AopProxy代理對象
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB2 proxy: target source is " + this.advised. getTargetSource()); } //從advised中取得在IoC容器中配置的target對象 try { Class rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class proxySuperClass = rootClass; if (AopUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class[] additionalInterfaces = rootClass.getInterfaces(); for (Class additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } //驗(yàn)證代理對象的接口設(shè)置 // 創(chuàng)建并配置CGLIB的Enhancer,這個(gè)Enhancer對象是CGLIB的主要操作類 Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } //設(shè)置Enhancer對象,包括設(shè)置代理接口,回調(diào)方法 //來自advised的IoC配置,比如使用AOP的DynamicAdvisedInterceptor攔截器 enhancer.setSuperclass(proxySuperClass); enhancer.setStrategy(new UndeclaredThrowableStrategy (UndeclaredThrowableException.class)); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setInterceptDuringConstruction(false); Callback[] callbacks = getCallbacks(rootClass); enhancer.setCallbacks(callbacks); enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); Class[] types = new Class[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } enhancer.setCallbackTypes(types); // 通過Enhancer生成代理對象 Object proxy; if (this.constructorArgs != null) { proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs); } else { proxy = enhancer.create(); } return proxy; } catch (CodeGenerationException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class",ex); } catch (IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or anon-visible class", ex); } catch (Exception ex) { throw new AopConfigException("Unexpected AOP exception", ex); } }
在代碼清單中,可以看到具體對CGLIB的使用,比如對Enhancer對象的配置,以及通過Enhancer對象生成代理對象的過程。在這個(gè)生成代理對象的過程中,需要注意的是對Enhancer對象callback回調(diào)的設(shè)置,正是這些回調(diào)封裝了Spring AOP的實(shí)現(xiàn),就像前面介紹的JDK的Proxy對象的invoke回調(diào)方法一樣。在Enhancer的callback回調(diào)設(shè)置中,實(shí)際上是通過設(shè)置DynamicAdvisedInterceptor攔截器來完成AOP功能的,如果讀者感興趣,可以在getCallbacks方法實(shí)現(xiàn)中看到回調(diào)DynamicAdvisedInterceptor的設(shè)置。
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
DynamicAdvisedInterceptor中的回調(diào)實(shí)現(xiàn)會在下面詳細(xì)分析,這里先埋一個(gè)伏筆。
這樣,通過使用AopProxy對象封裝target目標(biāo)對象之后,ProxyFactoryBean的getObject方法得到的對象就不是一個(gè)普通的Java對象了,而是一個(gè)AopProxy代理對象。在ProxyFactoryBean中配置的target目標(biāo)對象,這時(shí)已經(jīng)不會讓應(yīng)用直接調(diào)用其方法實(shí)現(xiàn),而是作為AOP實(shí)現(xiàn)的一部分。對target目標(biāo)對象的方法調(diào)用會首先被AopProxy代理對象攔截,對于不同的AopProxy代理對象生成方式,會使用不同的攔截回調(diào)入口。例如,對于JDK的AopProxy代理對象,使用的是InvocationHandler的invoke回調(diào)入口;而對于CGLIB的AopProxy代理對象,使用的是設(shè)置好的callback回調(diào),這是由對CGLIB的使用來決定的。在這些callback回調(diào)中,對于AOP實(shí)現(xiàn),是通過DynamicAdvisedInterceptor來完成的,而DynamicAdvisedInterceptor的回調(diào)入口是intercept方法。通過這一系列的準(zhǔn)備,已經(jīng)為實(shí)現(xiàn)AOP的橫切機(jī)制奠定了基礎(chǔ),在這個(gè)基礎(chǔ)上,AOP的Advisor已經(jīng)可以通過AopProxy代理對象的攔截機(jī)制,對需要它進(jìn)行增強(qiáng)的target目標(biāo)對象發(fā)揮切面的強(qiáng)大威力了。
可以把AOP的實(shí)現(xiàn)部分看成由基礎(chǔ)設(shè)施準(zhǔn)備和AOP運(yùn)行輔助這兩個(gè)部分組成,這里的AopProxy代理對象的生成,可以看成是一個(gè)靜態(tài)的AOP基礎(chǔ)設(shè)施的建立過程。通過這個(gè)準(zhǔn)備過程,把代理對象、攔截器這些待調(diào)用的部分都準(zhǔn)備好,等待著AOP運(yùn)行過程中對這些基礎(chǔ)設(shè)施的使用。對于應(yīng)用觸發(fā)的AOP應(yīng)用,會涉及AOP框架的運(yùn)行和對AOP基礎(chǔ)設(shè)施的使用。這些動態(tài)的運(yùn)行部分,是從前面提到的攔截器回調(diào)入口開始的,這些攔截器調(diào)用的實(shí)現(xiàn)原理,和AopProxy代理對象生成一樣,也是AOP實(shí)現(xiàn)的重要組成部分,同時(shí)也是下面要重點(diǎn)分析的內(nèi)容,讓我們繼續(xù)深入AopProxy代理對象的回調(diào)實(shí)現(xiàn)中去,慢慢地揭開Spring AOP實(shí)現(xiàn)的另一層神秘的面紗。
- Learning C# by Developing Games with Unity 2020
- C語言程序設(shè)計(jì)基礎(chǔ)與實(shí)驗(yàn)指導(dǎo)
- Java 9 Programming Blueprints
- Git高手之路
- Learning Firefox OS Application Development
- Microsoft System Center Orchestrator 2012 R2 Essentials
- Python編程與幾何圖形
- Learn React with TypeScript 3
- ArcGIS By Example
- 青少年學(xué)Python(第1冊)
- Arduino可穿戴設(shè)備開發(fā)
- MyBatis 3源碼深度解析
- Exploring SE for Android
- JavaScript編程精解(原書第2版)
- Java Hibernate Cookbook