新聞中心

創(chuàng)新互聯(lián)建站是專業(yè)的溫泉網(wǎng)站建設(shè)公司,溫泉接單;提供成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站,網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行溫泉網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!
概述
在Spring中創(chuàng)建AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean。這提供了對(duì)切入點(diǎn)、應(yīng)用的任何通知及其順序的完全控制。但是,如果你不需要這種控制,則有更簡(jiǎn)單的選項(xiàng)更可取。
和其他Spring FactoryBean實(shí)現(xiàn)一樣,ProxyFactoryBean引入了一個(gè)間接層。如果定義了一個(gè)名為foo的ProxyFactoryBean,那么引用foo的對(duì)象不會(huì)看到ProxyFactoryBean實(shí)例本身,而是看到一個(gè)由ProxyFactoryBean中的getObject()方法實(shí)現(xiàn)創(chuàng)建的對(duì)象。此方法創(chuàng)建封裝目標(biāo)對(duì)象的AOP代理。
使用ProxyFactoryBean或另一個(gè)支持IoC的類來(lái)創(chuàng)建AOP代理的最重要的好處之一是,IoC也可以管理Advice和Pointcut。這是一個(gè)強(qiáng)大的特性,可以實(shí)現(xiàn)某些用其他AOP框架難以實(shí)現(xiàn)的方法。例如,通知本身可以引用應(yīng)用程序?qū)ο?目標(biāo)之外,它應(yīng)該在任何AOP框架中可用),受益于依賴項(xiàng)注入提供的所有可插拔性。
ProxyFactoryBean 屬性
和Spring提供的大多數(shù)FactoryBean實(shí)現(xiàn)一樣,ProxyFactoryBean類本身就是一個(gè)JavaBean。它的屬性用于:
- 指定要代理的目標(biāo)
- 指定是否使用CGLIB
一些關(guān)鍵屬性繼承自org.springframework.aop.framework.ProxyConfig (Spring中所有AOP代理工廠的超類)。這些關(guān)鍵屬性包括: - proxyTargetClass: 如果要代理的是目標(biāo)類,而不是目標(biāo)類的接口,則為true。如果該屬性值設(shè)置為true,則創(chuàng)建CGLIB代理。
- optimize: 控制是否對(duì)通過(guò)CGLIB創(chuàng)建的代理應(yīng)用激進(jìn)的優(yōu)化。除非你完全理解相關(guān)AOP代理如何處理優(yōu)化,否則不應(yīng)該輕松地使用此設(shè)置。目前僅用于CGLIB代理。它對(duì)JDK動(dòng)態(tài)代理沒(méi)有影響。
- frozen: 如果代理配置被凍結(jié),則不再允許更改該配置。無(wú)論是作為輕微的優(yōu)化,還是當(dāng)你不希望調(diào)用者在創(chuàng)建代理后能夠操作代理,這都是有用的。此屬性的默認(rèn)值為false,因此允許更改(例如添加額外的通知)。
- exposeProxy: 確定是否應(yīng)該在ThreadLocal中暴露當(dāng)前代理,以便目標(biāo)可以訪問(wèn)它。如果目標(biāo)需要獲取代理,而exposeProxy屬性被設(shè)置為true,那么可以使用AopContext.currentProxy()方法。
ProxyFactoryBean特有的其他屬性包括:
- proxyInterfaces: 接口名稱的字符串?dāng)?shù)組。如果沒(méi)有提供,則使用目標(biāo)類的CGLIB代理
- interceptorNames: 建議器、攔截器或其他要應(yīng)用的建議器名稱的字符串?dāng)?shù)組。 這些名稱是當(dāng)前工廠中的bean名稱,包括來(lái)自祖先工廠的bean名稱。這里不能提到bean引用,因?yàn)檫@樣做會(huì)導(dǎo)致ProxyFactoryBean忽略通知的單例設(shè)置。
你可以在攔截器名稱后面加上星號(hào)(*)。這樣做的結(jié)果是,所有advisor bean的名稱都以要應(yīng)用的星號(hào)之前的部分開(kāi)頭。你可以在使用“全局”建議器中找到使用此功能的例子。 - singleton: 不管getObject()方法被調(diào)用的頻率如何,工廠是否應(yīng)該返回一個(gè)對(duì)象。有幾個(gè)FactoryBean實(shí)現(xiàn)提供了這樣的方法。默認(rèn)值為true。
基于JDK和CGLIB的代理
?ProxyFactoryBean如何選擇為特定目標(biāo)對(duì)象(要代理的對(duì)象)創(chuàng)建基于JDK的代理或基于CGLIB的代理的最終文檔。
如果要代理的目標(biāo)對(duì)象的類(以下簡(jiǎn)稱為目標(biāo)類)沒(méi)有實(shí)現(xiàn)任何接口,則創(chuàng)建一個(gè)基于cglib的代理。這是最簡(jiǎn)單的場(chǎng)景,因?yàn)镴DK代理是基于接口的,沒(méi)有接口意味著JDK代理根本不可能。你可以插入目標(biāo)bean并通過(guò)設(shè)置interceptorNames屬性來(lái)指定攔截器列表。注意,即使將ProxyFactoryBean的proxyTargetClass屬性設(shè)置為false,也會(huì)創(chuàng)建一個(gè)基于cglib的代理。
如果目標(biāo)類實(shí)現(xiàn)了一個(gè)(或多個(gè))接口,則創(chuàng)建的代理類型取決于ProxyFactoryBean的配置。
如果ProxyFactoryBean的proxyTargetClass屬性被設(shè)置為true,則會(huì)創(chuàng)建一個(gè)基于cglib的代理。這是有道理的,也符合最小意外原則。即使ProxyFactoryBean的proxyInterfaces屬性被設(shè)置為一個(gè)或多個(gè)完全限定的接口名,proxyTargetClass屬性被設(shè)置為true這一事實(shí)也會(huì)導(dǎo)致基于cglib的代理生效。
如果將ProxyFactoryBean的proxyInterfaces屬性設(shè)置為一個(gè)或多個(gè)完全限定的接口名,則創(chuàng)建一個(gè)基于jdk的代理。創(chuàng)建的代理實(shí)現(xiàn)了在proxyInterfaces屬性中指定的所有接口。如果目標(biāo)類碰巧實(shí)現(xiàn)了比proxyInterfaces屬性中指定的更多的接口,那也沒(méi)什么問(wèn)題,但返回的代理不會(huì)實(shí)現(xiàn)這些額外的接口。
如果ProxyFactoryBean的proxyInterfaces屬性沒(méi)有被設(shè)置,但是目標(biāo)類確實(shí)實(shí)現(xiàn)了一個(gè)(或多個(gè))接口,那么ProxyFactoryBean會(huì)自動(dòng)檢測(cè)到目標(biāo)類實(shí)際上至少實(shí)現(xiàn)了一個(gè)接口,并且創(chuàng)建了一個(gè)基于jdk的代理。實(shí)際被代理的接口是目標(biāo)類實(shí)現(xiàn)的所有接口。實(shí)際上,這相當(dāng)于為目標(biāo)類的proxyInterfaces屬性提供一個(gè)列表,其中包含目標(biāo)類實(shí)現(xiàn)的所有接口。然而,這樣做工作量大大減少,也不容易出現(xiàn)排版錯(cuò)誤。
代理接口
考慮一個(gè)使用ProxyFactoryBean的簡(jiǎn)單例子。這個(gè)例子涉及:
- 考慮一個(gè)使用ProxyFactoryBean的簡(jiǎn)單例子。這個(gè)例子涉及:
- 顧問(wèn)(Advisor)和攔截器(Interceptor)用來(lái)提供通知。
- 一個(gè)AOP代理bean定義,用來(lái)指定目標(biāo)對(duì)象(personTarget bean)、代理的接口和要應(yīng)用的建議。
myAdvisor
debugInterceptor
注意,interceptorNames屬性接受一個(gè)字符串列表,其中包含當(dāng)前工廠中攔截器或顧問(wèn)的bean名稱。你可以使用顧問(wèn),攔截器,返回之前,之后,并拋出建議對(duì)象。
前面給出的person bean定義可以代替person實(shí)現(xiàn),如下所示:
Person person = (Person) factory.getBean("person");同一個(gè)IoC上下文中的其他bean可以表達(dá)對(duì)它的強(qiáng)類型依賴,就像普通Java對(duì)象一樣。如下面的例子所示:
這個(gè)例子中的PersonUser類公開(kāi)了一個(gè)Person類型的屬性。就它所關(guān)心的而言,AOP代理可以透明地代替“真實(shí)的”人實(shí)現(xiàn)。但是,它的類將是一個(gè)動(dòng)態(tài)代理類。
代理類
如果需要代理一個(gè)類,而不是一個(gè)或多個(gè)接口,該怎么辦?
想象一下,在我們前面的例子中,沒(méi)有Person接口。我們需要建議一個(gè)名為Person的類,它沒(méi)有實(shí)現(xiàn)任何業(yè)務(wù)接口。在這種情況下,你可以配置Spring使用CGLIB代理,而不是動(dòng)態(tài)代理。為此,將前面給出的ProxyFactoryBean的proxyTargetClass屬性設(shè)置為true。雖然最好是針對(duì)接口而不是類進(jìn)行編程,但在處理遺留代碼時(shí),能夠建議不實(shí)現(xiàn)接口的類可能很有用。(一般來(lái)說(shuō),Spring不是規(guī)定性的。雖然它使應(yīng)用良好的實(shí)踐變得容易,但它避免了強(qiáng)制使用特定的方法。)
如果你愿意,你可以在任何情況下強(qiáng)制使用CGLIB,即使你有接口。
CGLIB代理通過(guò)在運(yùn)行時(shí)生成目標(biāo)類的子類來(lái)工作。Spring將這個(gè)生成的子類配置為將方法調(diào)用委托給原始目標(biāo)。子類用于實(shí)現(xiàn)裝飾器模式,在建議中編織。
CGLIB代理一般應(yīng)該對(duì)用戶透明。但是,有一些問(wèn)題需要考慮:
- Final方法無(wú)法提供建議,因?yàn)樗鼈儾荒鼙桓采w
- 不需要將CGLIB添加到類路徑中。從Spring 3.2開(kāi)始,CGLIB被重新打包并包含在Spring -core JAR中。換句話說(shuō),基于cglib的AOP可以“開(kāi)箱即用”,JDK的動(dòng)態(tài)代理也是如此
使用“全局”顧問(wèn)(Advisor)
通過(guò)在攔截器名稱后面附加一個(gè)星號(hào),所有bean名稱與星號(hào)之前的部分匹配的顧問(wèn)都被添加到顧問(wèn)鏈中。如果你需要添加一組標(biāo)準(zhǔn)的“全局”顧問(wèn),這可以派上用場(chǎng)。下面的例子定義了兩個(gè)全局advisor:
global*
網(wǎng)頁(yè)標(biāo)題:Spring使用ProxyFactoryBean創(chuàng)建代理對(duì)象
網(wǎng)頁(yè)地址:http://fisionsoft.com.cn/article/djjsgpe.html


咨詢
建站咨詢
