隨筆-61  評論-13  文章-19  trackbacks-0

          今天一看,Blog爬到了第一,又很久沒更新了,因此就把這兩天正在寫的電子書的一部分貼上吧。今天想找找Spring 2.0 AOP的例子,誰料想網(wǎng)上文章一大抄,而且呢,大部分人是直接copy Spring的文檔,自己連個(gè)demo也不寫一種的那個(gè),就見一堆文章說的云里霧里熱火朝天的AOP,也沒見著幾個(gè)能跑的例子。最后總算找到了個(gè)兄弟的小短文,有個(gè)能跑的例子,這才算弄好了1.2和2.0的對比部分。好了,下面是正文(其實(shí)尚未完工,先湊合看吧):

          10.3 開發(fā)Spring 1.2 AOP應(yīng)用

                 本節(jié)將會(huì)給大家展示一個(gè)恐怖的例子,FBI特務(wù)人員已經(jīng)介入了您的生活,您所做的一切都在他們的監(jiān)視之中,包括聊QQ,泡MM,這在現(xiàn)實(shí)生活中是真實(shí)存在的,為了民眾的安全和穩(wěn)定,對嫌疑犯進(jìn)行必要的監(jiān)控是必要的。

                 注意:本章雖然介紹了多種AOP實(shí)現(xiàn)方式,然而,在實(shí)際項(xiàng)目中只要使用一種就可以達(dá)到目的了(因?yàn)?/span>SpringAOP存在多種寫法,完全掌握還是挺復(fù)雜),其它方式僅供參考,千萬不要像孔乙己一樣,研究“茴”字的N種寫法,這樣就脫離了學(xué)習(xí)技術(shù)的初衷了:學(xué)習(xí)是為了解決問題,不是為了炫耀自己。另外,如果在項(xiàng)目中濫用AOP的后果就是系統(tǒng)的執(zhí)行效率大大降低,甚至配置不當(dāng)會(huì)導(dǎo)致死循環(huán)。記住一個(gè)真理:系統(tǒng)越復(fù)雜,效率越低,出故障的可能越大。另外一條建議:千萬不要用AOP在服務(wù)器上記錄日志,或者在服務(wù)器上打印不必要的調(diào)試信息,那樣對系統(tǒng)只能有害無益,日志輸出是單線程操作,切記。做項(xiàng)目,一般來說是功能越少越好。高手更多的時(shí)候只能做出破壞力大,不易維護(hù)的垃圾系統(tǒng)。

          10.3.1開發(fā)Man對象

                 這個(gè)項(xiàng)目非常簡單,仿照上節(jié)內(nèi)容,創(chuàng)建項(xiàng)目并添加Spring開發(fā)功能,不同的是添加library的時(shí)候要把Spring 2.0 AOP Libraries加入進(jìn)來。因?yàn)?/span>Spring 2.0的類庫是兼容1.2的,所以這里就用2.0了。項(xiàng)目名為Spring1_2AOP。接下來我們要?jiǎng)?chuàng)建一個(gè)自由人的對象,他有聊QQ和泡MM這兩個(gè)方法,還有一個(gè)姓名屬性。好了,先建立這個(gè)類:

          /**

           *具有聊QQ和泡MM兩個(gè)行為的人對象,還有一個(gè)用戶名屬性。

           *@authorBeanSoft

           */

          publicclass Man {

              private String name;

              public String getName() {

                 returnname;

              }

              publicvoid setName(String name) {

                 this.name = name;

              }

             

              publicvoid qq() {

                 System.out.println("我在聊QQ");

              }

             

              publicvoid mm() {

                 System.out.println("我在泡MM");

              }

          }

          清單10.6 Man類源碼

          10.3.2開發(fā)前置通知(Before advice)對象:FBI

                 首先貼一段Spring文檔中關(guān)于Before advice的介紹:

          前置通知(Before advice 在某連接點(diǎn)(join point)之前執(zhí)行的通知,但這個(gè)通知不能阻止連接點(diǎn)前的執(zhí)行(除非它拋出一個(gè)異常)。

          說通俗點(diǎn)就是寫一個(gè)如何處理監(jiān)視結(jié)果的對象,可以把監(jiān)視結(jié)果打印出來以作為必要的時(shí)候的呈堂證物,或者派探員立即跟蹤,但是這個(gè)過程只能在你進(jìn)行某活動(dòng)前進(jìn)行,否則就失去監(jiān)視的意義了,這個(gè)對象更像“諸葛亮”。詳細(xì)的了解這個(gè)類需要學(xué)習(xí)JDK里面關(guān)于反射部分的內(nèi)容,下面是這個(gè)類的代碼:

          import java.lang.reflect.Method;

          import org.springframework.aop.MethodBeforeAdvice;

          /**

           *聯(lián)邦調(diào)查局的探員將您的所有行動(dòng)都記錄在案。

           *@authorBeanSoft

           */

          publicclass FBI implements MethodBeforeAdvice {

              publicvoid before(Method method, Object[] args, Object target)

                     throws Throwable {

                 Man man = (Man)target;

                 System.err.println("FBI 發(fā)現(xiàn)" + man.getName() + "正在進(jìn)行 " + method.getName() + " 活動(dòng)。");

              }

          }

          清單10.7 FBI類源碼

          10.3.3裝配攔截器和Bean

                 最后要做的,就是創(chuàng)建一個(gè)平民對象,注意不是自由人哦,因?yàn)槠矫袷请S時(shí)處于FBI的監(jiān)視之下的。這個(gè)對象本質(zhì)上是類ProxyFactoryBean的一個(gè)示例,這個(gè)類位于包org.springframework.aop.framework下,自由人只能活在這個(gè)代理工廠類的陰影下了,也就是成了平民了。好了,我們把相應(yīng)的Spring配置文件代碼放給大家:

          <?xml version="1.0" encoding="UTF-8"?>

          <beans xmlns="http://www.springframework.org/schema/beans"

              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

              xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

             

              <bean id="man" class="Man">

                 <property name="name">

                     <value type="java.lang.String">張三</value>

                 </property>

              </bean>

              <bean id="fbi" class="FBI" />

             

              <bean id="civilian"

                 class="org.springframework.aop.framework.ProxyFactoryBean">

                 <property name="target">

                     <ref bean="man" />

                 </property>

                 <property name="interceptorNames">

                     <list>

                        <value>fbi</value>

                     </list>

                 </property>

              </bean>

          </beans>

          清單10.8 Spring AOP 配置文件源碼 applicationContext.xml

          在這個(gè)文件中,定義了兩個(gè)beanmanfbi,都是普通的類定義。復(fù)雜一些的地方在civilian這個(gè)bean的定義中,它要攔截或者監(jiān)視的目標(biāo)(target)是man,負(fù)責(zé)進(jìn)行處理監(jiān)視結(jié)果的對象(interceptorNames)是fbi,具體進(jìn)行監(jiān)視工作的對象,就是這個(gè)ProxyFactoryBean,它相當(dāng)于竊聽器之類的東西,但是很顯然竊聽結(jié)果是需要人來處理的,那就是FBI

          簡單說: man成為了civilian,它被ProxyFactoryBean監(jiān)控,監(jiān)控結(jié)果交給FBI處理。很顯然,如果沒有國家,也就沒有civilian,更談不上FBI了。所以,在這里您不能再去找man,因?yàn)?/span>man在實(shí)際生活中是不存在的,所以您只能找civilian,這樣您才能感覺到FBI的存在。下面是相關(guān)的bean關(guān)系圖:

          clip_image002

          10.9 Bean關(guān)系圖

          10.3.4測試和運(yùn)行

                 OK,如上節(jié)討論,只有當(dāng)平民的時(shí)候才會(huì)被監(jiān)視,現(xiàn)在我們就可以寫一個(gè)測試類來感受一下平民生活:

          import org.springframework.context.ApplicationContext;

          import org.springframework.context.support.ClassPathXmlApplicationContext;

          publicclass AOPTest {

              publicstaticvoid main(String[] args) {

                 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

                 Man man = (Man) ctx.getBean("civilian");

                 man.qq();

                 man.mm();

              }

          }

          清單10.9 Spring AOP 測試類源碼

          運(yùn)行一下,您就可以看到可怕的真相:

          log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).

          log4j:WARN Please initialize the log4j system properly.

          FBI 發(fā)現(xiàn)張三正在進(jìn)行 qq 活動(dòng)。

          FBI 發(fā)現(xiàn)張三正在進(jìn)行 mm 活動(dòng)。

          我在聊QQ

          我在泡MM

          是不是很恐怖呢?FBI正在監(jiān)控您的一舉一動(dòng),并把這些東西都記錄在案。現(xiàn)在你應(yīng)該可以了解AOP的過程了:調(diào)用man這個(gè)bean的任何一個(gè)方法之前,都會(huì)事先通知(調(diào)用)fbi這個(gè)bean并告知相關(guān)的調(diào)用信息,這些信息包括方法(method),參數(shù)(args)以及目標(biāo)對象(target,這里就是man這個(gè)對象)。

          如果你把上面的代碼改成ctx.getBean(“man”),那么自由人是不會(huì)被監(jiān)控的,所以這時(shí)候您就不會(huì)看到FBI輸出的恐怖信息了。此時(shí)的輸出如下:

          log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).

          log4j:WARN Please initialize the log4j system properly.

          我在聊QQ

          我在泡MM

          10.3.5 AOP簡介和相關(guān)概念

                 現(xiàn)在我們已經(jīng)寫了一個(gè)很簡單的Spring AOP 例子,現(xiàn)在就給大家簡單介紹一下相關(guān)的概念,這些信息來自于Spring的中文文檔。

          面向切面編程AOP)提供另外一種角度來思考程序結(jié)構(gòu),通過這種方式彌補(bǔ)了面向?qū)ο缶幊蹋?/span>OOP)的不足。 除了類(classes)以外,AOP提供了 切面。切面對關(guān)注點(diǎn)進(jìn)行模塊化,例如橫切多個(gè)類型和對象的事務(wù)管理。 (這些關(guān)注點(diǎn)術(shù)語通常稱作 橫切(crosscutting 關(guān)注點(diǎn)。)

          我們來定義一些重要的AOP概念。這些術(shù)語不是Spring特有的。不幸的是,Spring術(shù)語并不是特別的直觀;如果Spring使用自己的術(shù)語,將會(huì)變得更加令人困惑。

          l       切面(Aspect一個(gè)關(guān)注點(diǎn)的模塊化,這個(gè)關(guān)注點(diǎn)可能會(huì)橫切多個(gè)對象。事務(wù)管理是J2EE應(yīng)用中一個(gè)關(guān)于橫切關(guān)注點(diǎn)的很好的例子。Spring AOP中,切面可以使用通用類(基于模式的風(fēng)格)或者在普通類中以 @Aspect注解(@AspectJ風(fēng)格)來實(shí)現(xiàn)。

          l       連接點(diǎn)(Joinpoint在程序執(zhí)行過程中某個(gè)特定的點(diǎn),比如某方法調(diào)用的時(shí)候或者處理異常的時(shí)候。Spring AOP中,一個(gè)連接點(diǎn)總是代表一個(gè)方法的執(zhí)行。通過聲明一個(gè)org.aspectj.lang.JoinPoint類型的參數(shù)可以使通知(Advice)的主體部分獲得連接點(diǎn)信息。

          l       通知(Advice在切面的某個(gè)特定的連接點(diǎn)(Joinpoint)上執(zhí)行的動(dòng)作。通知有各種類型,其中包括“around”、“before”和“after”等通知。通知的類型將在后面部分進(jìn)行討論。許多AOP框架,包括Spring,都是以攔截器做通知模型,并維護(hù)一個(gè)以連接點(diǎn)為中心的攔截器鏈。

          l       切入點(diǎn)(Pointcut匹配連接點(diǎn)(Joinpoint)的斷言。通知和一個(gè)切入點(diǎn)表達(dá)式關(guān)聯(lián),并在滿足這個(gè)切入點(diǎn)的連接點(diǎn)上運(yùn)行(例如,當(dāng)執(zhí)行某個(gè)特定名稱的方法時(shí))。切入點(diǎn)表達(dá)式如何和連接點(diǎn)匹配是AOP的核心:Spring缺省使用AspectJ切入點(diǎn)語法。

          l       引入(Introduction(也被稱為內(nèi)部類型聲明(inter-type declaration))。聲明額外的方法或者某個(gè)類型的字段。 Spring允許引入新的接口(以及一個(gè)對應(yīng)的實(shí)現(xiàn))到任何被代理的對象。例如,你可以使用一個(gè)引入來使bean實(shí)現(xiàn)IsModified接口,以便簡化緩存機(jī)制。

          l       目標(biāo)對象(Target Object被一個(gè)或者多個(gè)切面(aspect)所通知(advise)的對象。也有人把它叫做被通知(advised對象。既然Spring AOP是通過運(yùn)行時(shí)代理實(shí)現(xiàn)的,這個(gè)對象永遠(yuǎn)是一個(gè)被代理(proxied對象。

          l       AOP代理(AOP Proxy): AOP框架創(chuàng)建的對象,用來實(shí)現(xiàn)切面契約(aspect contract)(包括通知方法執(zhí)行等功能)。Spring中,AOP代理可以是JDK動(dòng)態(tài)代理或者CGLIB代理。注意:Spring 2.0最新引入的基于模式(schema-based)風(fēng)格和@AspectJ注解風(fēng)格的切面聲明,對于使用這些風(fēng)格的用戶來說,代理的創(chuàng)建是透明的。

          l       織入(Weaving把切面(aspect)連接到其它的應(yīng)用程序類型或者對象上,并創(chuàng)建一個(gè)被通知(advised)的對象。這些可以在編譯時(shí)(例如使用AspectJ編譯器),類加載時(shí)和運(yùn)行時(shí)完成。 Spring和其他純Java AOP框架一樣,在運(yùn)行時(shí)完成織入。

          通知的類型:

          l       前置通知(Before advice在某連接點(diǎn)(join point)之前執(zhí)行的通知,但這個(gè)通知不能阻止連接點(diǎn)前的執(zhí)行(除非它拋出一個(gè)異常)。

          l       返回后通知(After returning advice在某連接點(diǎn)(join point)正常完成后執(zhí)行的通知:例如,一個(gè)方法沒有拋出任何異常,正常返回。

          l       拋出異常后通知(After throwing advice):在方法拋出異常退出時(shí)執(zhí)行的通知。

          l       后通知(After (finally) advice當(dāng)某連接點(diǎn)退出的時(shí)候執(zhí)行的通知(不論是正常返回還是異常退出)。

          l       環(huán)繞通知(Around Advice包圍一個(gè)連接點(diǎn)(join point)的通知,如方法調(diào)用。這是最強(qiáng)大的一種通知類型。環(huán)繞通知可以在方法調(diào)用前后完成自定義的行為。它也會(huì)選擇是否繼續(xù)執(zhí)行連接點(diǎn)或直接返回它們自己的返回值或拋出異常來結(jié)束執(zhí)行。

          環(huán)繞通知是最常用的一種通知類型。大部分基于攔截的AOP框架,例如Jboss,以及EJB 3里面的攔截器(后續(xù)章節(jié)我們會(huì)加以介紹),都只提供環(huán)繞通知。

          AspectJ一樣,Spring提供所有類型的通知,我們推薦你使用盡量簡單的通知類型來實(shí)現(xiàn)需要的功能。例如,如果你只是需要用一個(gè)方法的返回值來更新緩存,雖然使用環(huán)繞通知也能完成同樣的事情,但是你最好使用After returning通知而不是環(huán)繞通知。用最合適的通知類型可以使得編程模型變得簡單,并且能夠避免很多潛在的錯(cuò)誤。比如,你不需要調(diào)用JoinPoint(用于Around Advice)的proceed() 方法,就不會(huì)有調(diào)用的問題。

          Spring 2.0中,所有的通知參數(shù)都是靜態(tài)類型,因此你可以使用合適的類型(例如一個(gè)方法執(zhí)行后的返回值類型)作為通知的參數(shù)而不是使用一個(gè)對象數(shù)組。

          切入點(diǎn)(pointcut)和連接點(diǎn)(join point)匹配的概念是AOP的關(guān)鍵,這使得AOP不同于其它僅僅提供攔截功能的舊技術(shù)。切入點(diǎn)使得定位通知(advice)可獨(dú)立于OO層次。例如,一個(gè)提供聲明式事務(wù)管理的around通知可以被應(yīng)用到一組橫跨多個(gè)對象中的方法上(例如服務(wù)層的所有業(yè)務(wù)操作)。

          10.4 開發(fā) Spring 2.0 AOP 應(yīng)用

                 Spring 2.0實(shí)現(xiàn)了兩種方式的AOP配置,一種是基于XML配置文件式的,可以用在JDK1.4上,另一種是基于@AspectJ風(fēng)格的標(biāo)注(Annotation)進(jìn)行AOP開發(fā),可以用在JDK1.5的系統(tǒng)上。本節(jié)就對上節(jié)的應(yīng)用進(jìn)行改寫,使用Spring 2.0 AOP的方式來開發(fā)。關(guān)于Spring AOP的資料和相關(guān)概念的詳細(xì)信息,可以閱讀Spring的中文文檔。

          10.4.1使用aop 標(biāo)簽實(shí)現(xiàn)AOP

                 這種方式相對繁瑣,所不同的是不需要再定義ProxyFactoryBean的實(shí)例,而且自動(dòng)給相關(guān)的bean定義加入AOP功能,不在需要顯式的去訪問代理過的另外給出名字的bean定義了。

                 好了,現(xiàn)在讓我們新建一個(gè)項(xiàng)目,名為Spring2_0AOP,并按照10.3節(jié)內(nèi)容設(shè)置好必要的類庫和必要的文件。那么再這個(gè)例子中,Man類的代碼不需要做任何修改。需要改的是FBI這個(gè)類,而且它也不需要再實(shí)現(xiàn)某些接口了,類的源碼如下所示:

          import org.aspectj.lang.JoinPoint;

          /**

           *聯(lián)邦調(diào)查局的探員將您的所有行動(dòng)都記錄在案。

           *@authorBeanSoft

           */

          publicclass FBI {

              publicvoid before(JoinPoint point){

                 Man man = (Man)point.getTarget();

                

                 System.err.println("FBI 發(fā)現(xiàn)" + man.getName() + "正在進(jìn)行 " +

                        point.getSignature().getName() + " 活動(dòng)。");

              }

          }

          清單10.10 FBI類源碼

          注意這個(gè)類里面的方法 before(JoinPoint),方法名可以是任意的,可以帶一個(gè)JoinPoint類型的參數(shù),也可以不帶參數(shù)直接寫成before(),但是這個(gè)連接點(diǎn)(JoinPoint)對象帶來了所有和這次方法調(diào)用有關(guān)的信息,包括方法參數(shù),目標(biāo)對象等等,所以一般要做日志記錄的話會(huì)帶上它。

                 接下來是測試類的代碼,和以前的幾乎沒有任何不同,只不過現(xiàn)在直接訪問的是man這個(gè)bean。源碼如下所示:

          import org.springframework.context.ApplicationContext;

          import org.springframework.context.support.ClassPathXmlApplicationContext;

          publicclass AOPTest {

              publicstaticvoid main(String[] args) {

                 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

                 Man man = (Man) ctx.getBean("man");

                 man.qq();

                 man.mm();

              }

          }

          清單10.11 測試類AOPTest源碼

          這個(gè)類的執(zhí)行結(jié)果和上面的例子是類似的,如下所示:

          log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).

          log4j:WARN Please initialize the log4j system properly.

          FBI 發(fā)現(xiàn)張三正在進(jìn)行 qq 活動(dòng)。

          我在聊QQ

          FBI 發(fā)現(xiàn)張三正在進(jìn)行 mm 活動(dòng)。

          我在泡MM

          下面再介紹配置文件的寫法,先看看完整的配置文件代碼:

          <?xml version="1.0" encoding="UTF-8"?>

          <beans xmlns="http://www.springframework.org/schema/beans"

              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

              xmlns:aop="http://www.springframework.org/schema/aop"

              xsi:schemaLocation="

                 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

                 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

              <bean id="fbi" class="FBI" />

              <bean id="man" class="Man">

                 <property name="name">

                     <value type="java.lang.String">張三</value>

                 </property>

              </bean>

             

                 <aop:config>

                        <aop:pointcut id="manPointcut"

                               expression="execution(* Man.*(..))" />

                        <aop:aspect id="beforeExample" ref="fbi">

                               <aop:before pointcut-ref="manPointcut" method="before" />

                        </aop:aspect>

                 </aop:config>

          </beans>

          清單10.12 AOP XML格式配置文件源碼applicationContext.xml

          將這個(gè)配置文件的代碼和清單10.8進(jìn)行對比,可以看到兩個(gè)不同:

          1.        配置文件的開頭加入了aop命名空間,如代碼中粗斜體所示。

          2.        使用aop:config標(biāo)簽來定義AOP,不是使用ProxyFactoryBean來定義一個(gè)新的bean

          簡要介紹一下這個(gè)配置。兩個(gè)bean的定義都沒有什么大的變化,一個(gè)是人的對象,另一個(gè)則是聯(lián)邦調(diào)查局的探員。而aop:config中定義了所有的AOP設(shè)置信息。aop:pointcut定義了一個(gè)切入點(diǎn),id給出了這個(gè)切入點(diǎn)的唯一名字,而expression定義了切入點(diǎn)的表達(dá)式,那么這個(gè)定義到底表示了什么信息呢?它的意思是表示一種場景,即執(zhí)行(executionMan對象的所有方法的這種情況,這就是表達(dá)式execution(* Man.*(..))的意義所在,Man.*(..)表示Man類的所有方法。接下來呢,需要定義一個(gè)切面,用aop:aspect來定義,它的ref屬性指定了這個(gè)切面所對應(yīng)的bean定義的id,這里指向fbi這個(gè)bean類;子標(biāo)簽aop:before則指示了當(dāng)發(fā)生了名為manPointcut的切入點(diǎn)(情況)前(用pointcut-ref屬性指定,pointcut-ref”manPointcut”),就調(diào)用名為before的方法,這個(gè)方法位于aspect里面的引用的那個(gè)bean中,這里是fbi(即ref=”fbi”)。其實(shí)Spring執(zhí)行到這里后,會(huì)自動(dòng)的把這些代碼翻譯成底層的Bean定義(后臺(tái)依然會(huì)采用ProxyFactoryBean這樣的機(jī)制),然后把對應(yīng)的獲取bean的操作直接委托給代理類,這就是為什么上文提到的測試類只需要訪問原來的man這個(gè)bean,對應(yīng)的攔截類就會(huì)被執(zhí)行的原因。從這里看到Spring 2.0中要定義一個(gè)AOPbean類,仍然是比較復(fù)雜的,XML文件和概念都增加了很多,需要讀者慢慢來學(xué)習(xí)和理解。

                 本節(jié)的詳細(xì)參考資料可以閱讀Spring參考文檔的6.3. Schema-based AOP support一節(jié)。

          10.4.2使用標(biāo)注(@AspectJ)實(shí)現(xiàn)AOP

                 下面的文檔來自于Spring"@AspectJ"使用了Java 5的注解,可以將切面聲明為普通的Java類。 AspectJ 5發(fā)布的 AspectJ project http://www.eclipse.org/aspectj)中引入了這種@AspectJ風(fēng)格。 Spring 2.0 使用了和AspectJ 5一樣的注解,使用了AspectJ 提供的一個(gè)庫來做切點(diǎn)(pointcut)解析和匹配。

                 為了在Spring配置中使用@AspectJ aspects,你必須首先啟用Spring對基于@AspectJ aspects的配置支持,自動(dòng)代理(autoproxying)基于通知是否來自這些切面。 自動(dòng)代理是指Spring會(huì)判斷一個(gè)bean是否使用了一個(gè)或多個(gè)切面通知,并據(jù)此自動(dòng)生成相應(yīng)的代理以攔截其方法調(diào)用,并且確認(rèn)通知是否如期進(jìn)行。

          通過在你的Spring的配置文件中引入下列元素來啟用Spring@AspectJ的支持:

          <aop:aspectj-autoproxy/>

          也可以通過在你的application context中添加如下定義來啟用@AspectJ支持:

          <bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />

          你需要在你的應(yīng)用程序的classpath中引入兩個(gè)AspectJ庫:aspectjweaver.jar aspectjrt.jar。我們這里用的MyEclipse,在添加Spring開發(fā)功能時(shí)已經(jīng)自動(dòng)的加入了這些類庫文件,無需手工配置了。

                 定義切面Aspect:在啟用@AspectJ支持的情況下,在application context中定義的任意帶有一個(gè)@Aspect切面(擁有@Aspect注解)的bean都將被Spring自動(dòng)識(shí)別并用于配置在Spring AOP

                 定義切入點(diǎn)Pointcut:現(xiàn)在通過在 @AspectJ 注解風(fēng)格的 AOP 中,一個(gè)切入點(diǎn)簽名通過一個(gè)普通的方法定義來提供,并且切入點(diǎn)表達(dá)式使用 @Pointcut 注解來表示(作為切入點(diǎn)簽名的方法必須返回 void 類型)。

                 好了,引用了這么些文檔,我們需要介紹這個(gè)基于標(biāo)注的新的AOP項(xiàng)目了,這個(gè)項(xiàng)目的名字是Spring2_0AOPAspectJ,如前一節(jié)所示加入了Spring核心和AOP類庫后,就可以開發(fā)了。那么相比較10.4.1 使用aop 標(biāo)簽實(shí)現(xiàn)AOP一節(jié),這一個(gè)項(xiàng)目的代碼僅僅有兩個(gè)地方要改。首先我們要修改FBI類的源碼,加入標(biāo)注來實(shí)現(xiàn)切面和切入點(diǎn)定義,如下所示:

          import org.aspectj.lang.JoinPoint;

          import org.aspectj.lang.annotation.Aspect;

          import org.aspectj.lang.annotation.Before;

          /**

           *聯(lián)邦調(diào)查局的探員將您的所有行動(dòng)都記錄在案。

           *@authorBeanSoft

           */

          @Aspect

          publicclass FBI {

              @Before("execution(* Man.*(..))")

              publicvoid before(JoinPoint point){

                 Man man = (Man)point.getTarget();

                

                 System.err.println("FBI 發(fā)現(xiàn)" + man.getName() + "正在進(jìn)行 " +

                        point.getSignature().getName() + " 活動(dòng)。");

              }

          }

          清單10.12 加入了Aspect標(biāo)注的FBI

          這個(gè)類中的@Before后面的"execution(* Man.*(..))"是切入點(diǎn)所對應(yīng)的切入點(diǎn)表達(dá)式,其意義和上一節(jié)的是一致的,仍然表示的是執(zhí)行 Man 類的所有方法時(shí)將觸發(fā)此方法的執(zhí)行。

          posted on 2010-01-25 11:10 xnabx 閱讀(1035) 評論(1)  編輯  收藏

          評論:
          # re: Spring 1.2和2.0的簡單AOP例子 (轉(zhuǎn)) 2011-10-21 11:14 | 也許
          受益匪淺 謝謝  回復(fù)  更多評論
            

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 汝阳县| 南开区| 环江| 云安县| 正安县| 吉安县| 徐汇区| 绥宁县| 本溪| 兰坪| 迭部县| 札达县| 磐安县| 余姚市| 康保县| 清徐县| 永寿县| 且末县| 临洮县| 舞钢市| 辽中县| 长治市| 三穗县| 无棣县| 扎兰屯市| 额敏县| 六盘水市| 浏阳市| 深泽县| 台前县| 兰州市| 锦州市| 阳东县| 大荔县| 清苑县| 洪洞县| 广灵县| 乌拉特前旗| 沁水县| 维西| 榆林市|