日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

使用ProxyFactoryBean创建AOP代理 - Spring Framework reference 2.0.5 参考手册中文版

發(fā)布時間:2024/4/17 javascript 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用ProxyFactoryBean创建AOP代理 - Spring Framework reference 2.0.5 参考手册中文版 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

http://doc.javanb.com/spring-framework-reference-zh-2-0-5/ch07s05.html

7.5.?使用ProxyFactoryBean創(chuàng)建AOP代理

如果你正在使用Spring IoC容器(即ApplicationContext或BeanFactory)來管理你的業(yè)務對象--這正是你應該做的--你也許會想要使用Spring中關于AOP的FactoryBean。(記住使用工廠bean引入一個間接層之后,我們就可以創(chuàng)建不同類型的對象了)。

注意

Spring 2.0的AOP支持也在底層使用工廠bean。

在Spring里創(chuàng)建一個AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean。這個類對應用的切入點和通知提供了完整的控制能力(包括它們的應用順序)。然而如果你不需要這種控制,你會喜歡更簡單的方式。

7.5.1.?基礎

像其它的FactoryBean實現(xiàn)一樣,ProxyFactoryBean引入了一個間接層。如果你定義一個名為foo的ProxyFactoryBean, 引用foo的對象看到的將不是ProxyFactoryBean實例本身,而是一個ProxyFactoryBean實現(xiàn)里getObject() 方法所創(chuàng)建的對象。 這個方法將創(chuàng)建一個AOP代理,它包裝了一個目標對象。

使用ProxyFactoryBean或者其它IoC相關類帶來的最重要的好處之一就是創(chuàng)建AOP代理,這意味著通知和切入點也可以由IoC來管理。這是一個強大的功能并使得某些特定的解決方案成為可能, 而這些用其它AOP框架很難做到。例如,一個通知也許本身也要引用應用程序對象(不僅僅是其它AOP框架中也可以訪問的目標對象),這令你可以從依賴注射的可拔插特性中獲益。

7.5.2.?JavaBean屬性

通常情況下Spring提供了大多數(shù)的FactoryBean實現(xiàn),ProxyFactoryBean類本身也是一個JavaBean。它的屬性被用來:

  • 指定你希望代理的目標對象

  • 指定是否使用CGLIB(查看下面叫做第?7.5.3?節(jié) “基于JDK和CGLIB的代理”的小節(jié))。

一些主要屬性從org.springframework.aop.framework.ProxyConfig里繼承下來(這個類是Spring里所有AOP代理工廠的父類)。這些主要屬性包括:

  • proxyTargetClass:這個屬性為true時,目標類本身被代理而不是目標類的接口。如果這個屬性值被設為true,CGLIB代理將被創(chuàng)建(可以參看下面名為第?7.5.3?節(jié) “基于JDK和CGLIB的代理”的章節(jié))。

  • optimize:用來控制通過CGLIB創(chuàng)建的代理是否使用激進的優(yōu)化策略。除非完全了解AOP代理如何處理優(yōu)化,否則不推薦用戶使用這個設置。目前這個屬性僅用于CGLIB代理;對于JDK動態(tài)代理(缺省代理)無效。

  • frozen:用來控制代理工廠被配置之后,是否還允許修改通知。缺省值為false(即在代理被配置之后,不允許修改代理的配置)。

  • exposeProxy:決定當前代理是否被保存在一個ThreadLocal中以便被目標對象訪問。(目標對象本身可以通過MethodInvocation來訪問,因此不需要ThreadLocal。) 如果個目標對象需要獲取代理而且exposeProxy屬性被設為true,目標對象可以使用AopContext.currentProxy()方法。

  • aopProxyFactory:使用AopProxyFactory的實現(xiàn)。這提供了一種方法來自定義是否使用動態(tài)代理,CGLIB或其它代理策略。 缺省實現(xiàn)將根據(jù)情況選擇動態(tài)代理或者CGLIB。一般情況下應該沒有使用這個屬性的需要;它是被設計來在Spring 1.1中添加新的代理類型的。

ProxyFactoryBean中需要說明的其它屬性包括:

  • proxyInterfaces:需要代理的接口名的字符串數(shù)組。如果沒有提供,將為目標類使用一個CGLIB代理(也可以查看下面名為第?7.5.3?節(jié) “基于JDK和CGLIB的代理”的章節(jié))。

  • interceptorNames:Advisor的字符串數(shù)組,可以包括攔截器或其它通知的名字。順序是很重要的,排在前面的將被優(yōu)先服務。就是說列表里的第一個攔截器將能夠第一個攔截調用。

    這里的名字是當前工廠中bean的名字,包括父工廠中bean的名字。這里你不能使用bean的引用因為這會導致ProxyFactoryBean忽略通知的單例設置。

    你可以把一個攔截器的名字加上一個星號作為后綴(*)。這將導致這個應用程序里所有名字以星號之前部分開頭的advisor都被應用。你可以在第?7.5.6?節(jié) “使用“全局”advisor” 發(fā)現(xiàn)一個使用這個特性的例子。

  • 單例:工廠是否應該返回同一個對象,不論方法getObject()被調用的多頻繁。多個FactoryBean實現(xiàn)都提供了這個方法。缺省值是true。如果你希望使用有狀態(tài)的通知--例如,有狀態(tài)的mixin--可以把單例屬性的值設置為false來使用原型通知。

7.5.3.?基于JDK和CGLIB的代理

這個小節(jié)作為說明性文檔,解釋了對于一個目標對象(需要被代理的對象),ProxyFactryBean是如何決定究竟創(chuàng)建一個基于JDK還是CGLIB的代理的。

注意

ProxyFactoryBean需要創(chuàng)建基于JDK還是CGLIB代理的具體行為在版本1.2.x和2.0中有所不同。現(xiàn)在ProxyFactoryBean在關于自動檢測接口方面使用了與TransactionProxyFactoryBean相似的語義。

如果一個需要被代理的目標對象的類(后面將簡單地稱它為目標類)沒有實現(xiàn)任何接口,那么一個基于CGLIB的代理將被創(chuàng)建。這是最簡單的場景,因為JDK代理是基于接口的,沒有接口意味著沒有使用JDK進行代理的可能。 在目標bean里將被插入探測代碼,通過interceptorNames屬性給出了攔截器的列表。注意一個基于CGLIB的代理將被創(chuàng)建即使ProxyFactoryBean的proxyTargetClass屬性被設置為false。 (很明顯這種情況下對這個屬性進行設置是沒有意義的,最好把它從bean的定義中移除,因為雖然這只是個多余的屬性,但在許多情況下會引起混淆。)

如果目標類實現(xiàn)了一個(或者更多)接口,那么創(chuàng)建代理的類型將根據(jù)ProxyFactoryBean的配置來決定。

如果ProxyFactoryBean的proxyTargetClass屬性被設為true,那么一個基于CGLIB的代理將創(chuàng)建。這樣的規(guī)定是有意義的,遵循了最小驚訝法則(保證了設定的一致性)。 甚至當ProxyFactoryBean的proxyInterfaces屬性被設置為一個或者多個全限定接口名,而proxyTargetClass屬性被設置為true仍然實際使用基于CGLIB的代理。

如果ProxyFactoryBean的proxyInterfaces屬性被設置為一個或者多個全限定接口名,一個基于JDK的代理將被創(chuàng)建。被創(chuàng)建的代理將實現(xiàn)所有在proxyInterfaces屬性里被說明的接口;如果目標類實現(xiàn)了全部在proxyInterfaces屬性里說明的接口以及一些額外接口,返回的代理將只實現(xiàn)說明的接口而不會實現(xiàn)那些額外接口。

如果ProxyFactoryBean的proxyInterfaces屬性沒有被設置,但是目標類實現(xiàn)了一個(或者更多)接口,那么ProxyFactoryBean將自動檢測到這個目標類已經(jīng)實現(xiàn)了至少一個接口, 一個基于JDK的代理將被創(chuàng)建。被實際代理的接口將是目標類所實現(xiàn)的全部接口;實際上,這和在proxyInterfaces屬性中列出目標類實現(xiàn)的每個接口的情況是一樣的。然而,這將顯著地減少工作量以及輸入錯誤的可能性。

7.5.4.?對接口進行代理

讓我們看一個關于ProxyFactoryBean的簡單例子。這個例子涉及:

  • 一個將被代理的目標bean。在下面的例子里這個bean是“personTarget”。

  • 被用來提供通知的一個advisor和一個攔截器。

  • 一個AOP代理bean的定義,它說明了目標對象(personTarget bean)以及需要代理的接口,還包括需要被應用的通知。

<bean id="personTarget" class="com.mycompany.PersonImpl"><property name="name"><value>Tony</value></property><property name="age"><value>51</value></property> </bean><bean id="myAdvisor" class="com.mycompany.MyAdvisor"><property name="someProperty"><value>Custom string property value</value></property> </bean><bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"> </bean><bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="proxyInterfaces"><value>com.mycompany.Person</value></property><property name="target"><ref local="personTarget"/></property><property name="interceptorNames"><list><value>myAdvisor</value><value>debugInterceptor</value></list></property> </bean>

注意interceptorNames屬性接受一組字符串:當前工廠中攔截器或advisorbean的名字。攔截器,advisor,前置, 后置和異常通知對象都可以在這里被使用。這里advisor的順序是很重要的。

注意

你也許很奇怪為什么這個列表不保存bean的引用。理由是如果ProxyFactoryBean的singleton屬性被設置為false,它必須返回獨立的代理實例。如果任何advisor本身是一個原型,則每次都返回一個獨立實例,因此它必須能夠從工廠里獲得原型的一個實例;保存一個引用是不夠的。

上面“person” bean的定義可以被用來取代一個Person接口的實現(xiàn),就像下面這樣:

Person person = (Person) factory.getBean("person");

在同一個IoC上下文中其它的bean可以對這個bean有基于類型的依賴,就像對一個普通的Java對象那樣:

<bean id="personUser" class="com.mycompany.PersonUser"><property name="person"><ref local="person" /></property> </bean>

這個例子里的PersonUser類將暴露一個類型為Person的屬性。就像我們關心的那樣,AOP代理可以透明地取代一個“真實”的person接口實現(xiàn)。然而,它的類將是一個動態(tài)代理類。 它可以被轉型成Advised接口(將在下面討論)。

就像下面這樣,你可以使用一個匿名內部bean來隱藏目標和代理之間的區(qū)別。僅僅ProxyFactoryBean的定義有所不同;通知的定義只是由于完整性的原因而被包括進來:

<bean id="myAdvisor" class="com.mycompany.MyAdvisor"><property name="someProperty"><value>Custom string property value</value></property> </bean><bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"/><bean id="person" class="org.springframework.aop.framework.ProxyFactor Bean"><property name="proxyInterfaces"><value>com.mycompany.Person</value></property><!-- Use inner bean, not local reference to target --><property name="target"><bean class="com.mycompany.PersonImpl"><property name="name"><value>Tony</value></property><property name="age"><value>51</value></property></bean></property><property name="interceptorNames"><list><value>myAdvisor</value><value>debugInterceptor</value></list></property> </bean>

對于只需要一個Person類型對象的情況,這是有好處的:如果你希望阻止應用程序上下文的用戶獲取一個指向未通知對象的引用或者希望避免使用Spring IoC 自動織入 時的混淆。 按理說ProxyFactoryBean定義還有一個優(yōu)點是它是自包含的。然而,有時能夠從工廠里獲取未通知的目標也是一個優(yōu)點:例如,在某些測試場景里。

7.5.5.?對類進行代理

如果你需要代理一個類而不是代理一個或是更多接口,那么情況將是怎樣?

想象在我們上面的例子里,不存在Person接口:我們需要通知一個叫做Person的類,它沒有實現(xiàn)任何業(yè)務接口。在這種情況下,你可以配置Spring使用CGLIB代理,而不是動態(tài)代理。 這只需簡單地把上面ProxyFactoryBean的proxyTargetClass屬性設為true。雖然最佳方案是面向接口編程而不是類,但在與遺留代碼一起工作時,通知沒有實現(xiàn)接口的類的能力是非常有用的。(通常情況下,Spring沒有任何規(guī)定。它只是讓你很容易根據(jù)實際情況選擇最好的解決方案,避免強迫使用特定方式)。

也許你希望你能夠在任何情況下都強制使用CGLIB,甚至在你使用接口的時候也這樣做。

CGLIB通過在運行時生成一個目標類的子類來進行代理工作。Spring配置這個生成的子類對原始目標對象的方法調用進行托管:子類實現(xiàn)了裝飾器(Decorator)模式,把通知織入。

CGLIB的代理活動應當對用戶是透明的。然而,有一些問題需要被考慮:

  • Final方法不可以被通知,因為它們不能被覆蓋。

  • 你需要在你的類路徑里有CGLIB 2的庫;使用動態(tài)代理的話只需要JDK。

在CGLIB代理和動態(tài)代理之間的速度差別是很小的。在Spring 1.0中,動態(tài)代理會快一點點。但這點可能在將來被改變。這種情況下,選擇使用何種代理時速度不應該成為決定性的理由。

7.5.6.?使用“全局”advisor

通過在一個攔截器名后添加一個星號,所有bean名字與星號之前部分相匹配的通知都將被加入到advisor鏈中。這讓你很容易添加一組標準的“全局”advisor:

<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="target" ref="service"/><property name="interceptorNames"><list><value>globa *</value></list></property> </bean><bean id="global_debug" class="org.springframework.aop.interceptor.DebugInterceptor"/> <bean id="global_performance" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>

?

總結

以上是生活随笔為你收集整理的使用ProxyFactoryBean创建AOP代理 - Spring Framework reference 2.0.5 参考手册中文版的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。