posts - 11,  comments - 9,  trackbacks - 0
          作者:      出處:it實驗室    http://dev.yesky.com

          本文介紹了使您可以使用Spring中的面向方面特性進行快速開發(fā)的基礎(chǔ)知識。
               

          作為這個介紹Spring框架中的面向方面編程(Aspect-Oriented Programming,AOP)的系列的第一部分,本文介紹了使您可以使用Spring中的面向方面特性進行快速開發(fā)的基礎(chǔ)知識。使用跟蹤和記錄方面(面向方面領(lǐng)域的HelloWorld)作為例子,本文展示了如何使用Spring框架所獨有的特性來聲明切入點和通知以便應(yīng)用方面。本系列的第二部分將更深入地介紹如何運用Spring中的所有通知類型和切入點來實現(xiàn)更實用的方面和面向方面設(shè)計模式。對于AOP的更一般性的介紹,請查看ONJava站點上Graham O'Regan的文章,“Introduction to Aspect-Oriented Programming”。

            本文的目的不是要介紹構(gòu)成模塊化J2EE系統(tǒng)——即Spring框架——的所有重要元素,我們將只把注意力放在Spring所提供的AOP功能上。由于Spring的模塊化設(shè)計方法,我們可以只使用該框架的AOP元素,而無需對構(gòu)成Spring框架的其他模塊做太多考慮。

            在AOP方面,Spring提供了什么?

            “它的目標(biāo)不是提供最完善的AOP實現(xiàn)(雖然Spring AOP非常強大);而是要提供AOP實現(xiàn)與Spring IoC的緊密集成,以便幫助解決企業(yè)應(yīng)用中的常見問題。”

            Spring Framework參考文檔

            為了實現(xiàn)這個目標(biāo),Spring框架目前支持一組AOP概念,從切入點到通知。本文將展示如何使用Spring框架中所實現(xiàn)的如下AOP概念:

            通知(Advice):如何將before通知、afterReturning通知和afterThrowing通知聲明為bean。

            切入點(Pointcut):如何聲明靜態(tài)切入點邏輯以將XML Spring Bean Configuration文件中的所有內(nèi)容聯(lián)系在一起。

            Advisor:關(guān)聯(lián)切入點定義與通知bean的方式。

            設(shè)置場景:一個簡單的例子應(yīng)用程序

            “一般而言,Spring并不是預(yù)描述的。雖然使用好的實踐非常容易,但是它避免強制推行一種特定的方法。”

            Spring Framework參考文檔

            要試用Spring框架的AOP功能,首先我們要創(chuàng)建一個簡單的Java應(yīng)用程序。IbusinessLogic接口和BusinessLogic類為Spring框架中的bean提供了簡易構(gòu)件塊。雖然該接口對于我們的簡單應(yīng)用程序邏輯來說不是必需的,但是它是Spring框架所推薦的良好實踐。

          public interface IBusinessLogic
          {
           public void foo();
          }

          public class BusinessLogic
          implements IBusinessLogic
          {
           public void foo()
           {
            System.out.println("Inside BusinessLogic.foo()");
           }
          }

            可以編寫MainApplication類,借此練習(xí)BusinessLogic bean的公有方法。

          import org.springframework.context.ApplicationContext;
          import org.springframework.context.support.FileSystemXmlApplicationContext;

          public class MainApplication
          {
           public static void main(String [] args)
           {
            // Read the configuration file
            ApplicationContext ctx =new FileSystemXmlApplicationContext("springconfig.xml");

            //Instantiate an object
            IBusinessLogic testObject =(IBusinessLogic) ctx.getBean("businesslogicbean");

            // Execute the public
            // method of the bean
            testObject.foo();
           }
          }

            在BusinessLogic類及其關(guān)聯(lián)接口中沒有什么需要注意的。但是,MainApplication類初始化BusinessLogic對象的方式很有意思。通過使用ctx.getBean("businesslogicbean")調(diào)用,MainApplication將加載和管理BusinessLogic類的bean實例的任務(wù)轉(zhuǎn)交給了Spring框架。

            允許Spring控制BusinessLogic bean的初始化,這使得Spring運行時有機會在bean被返回給應(yīng)用程序之前執(zhí)行J2EE系統(tǒng)所需的所有與bean相關(guān)的管理任務(wù)。然后Spring運行時配置可以決定對bean應(yīng)用哪些任務(wù)和模塊。該配置信息由一個XML文件提供,類似于下面所示的:

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC
          "-//SPRING//DTD BEAN//EN"
          "http://www.springframework.org/dtd/spring-beans.dtd">

          <beans>

           <!-- Bean configuration -->
           <bean id="businesslogicbean" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="proxyInterfaces">
             <value>IBusinessLogic</value>
            </property>
            <property name="target">
             <ref local="beanTarget"/>
            </property>
           </bean>
           <!-- Bean Classes -->
           <bean id="beanTarget" class="BusinessLogic"/>
           </beans>
          </BEANS>

            該配置文件,即springconfig.xml,指定要加載一個接口與IbusinessLogic相匹配的bean。該bean隨后被關(guān)聯(lián)到BusinessLogic實現(xiàn)類。看起來好像是費了很大力氣只為了加載一個簡單的bean并調(diào)用一個方法,但是您要知道,這個配置文件只是使Spring框架可以透明地對應(yīng)用程序應(yīng)用其組件的眾多特性的一個體現(xiàn)。

            圖1顯示了基本的順序圖:MainApplication原樣執(zhí)行,沒有應(yīng)用方面。
                


             圖1.沒有對BusinessLogic bean應(yīng)用方面時的順序圖




          應(yīng)用方法跟蹤(Method Tracing)方面

            可能最基本的方面就是方法跟蹤方面了。這可能是您找得到的最簡單的方面了,因此它是研究新的AOP實現(xiàn)的一個很好的起點。

            方法跟蹤方面在一個目標(biāo)應(yīng)用程序內(nèi)捕獲對所跟蹤的方法的調(diào)用以及方法的返回值,并以某種方式顯示這種信息。在AOP中,通知的before和after類型用于捕獲這些類型的聯(lián)結(jié)點,因為這兩種通知可以在方法調(diào)用聯(lián)結(jié)點之前或之后觸發(fā)。使用Spring框架,方法跟蹤方面的before通知是在TracingBeforeAdvice類中聲明的。

          import java.lang.reflect.Method;
          import org.springframework.aop. MethodBeforeAdvice;

          public class TracingBeforeAdvice
          implements MethodBeforeAdvice
          {
           public void before(Method m,Object[] args,Object target)
           throws Throwable
           {
            System.out.println("Hello world! (by " +this.getClass().getName() +")");
           }
          }

            類似地,after通知可以在TracingAfterAdvice類中聲明。

          import java.lang.reflect.Method;
          import org.springframework.aop.AfterReturningAdvice;

          public class TracingAfterAdvice
          implements AfterReturningAdvice
          {
           public void afterReturning(Object object,Method m,Object[] args,Object target)
           throws Throwable
           {
            System.out.println("Hello world! (by " +this.getClass().getName() +")");
           }
          }

            這兩個類都通過實現(xiàn)Spring框架的適當(dāng)通知接口而表示了特定的通知。每種類型的通知都指定實現(xiàn)before(..)或afterReturning(..)方法,以便使Spring運行時可以告訴通知適當(dāng)?shù)穆?lián)結(jié)點會在何時出現(xiàn)。值得注意的是,TracingAfterAdvice實際上是從AfterReturningAdvice擴展而來的,表示只有在聯(lián)結(jié)點在無異常的情況下獲得返回值時才運行通知。

            為了將通知與應(yīng)用程序中的適當(dāng)聯(lián)結(jié)點關(guān)聯(lián)起來,必須對springconfig.xml進行一些修改。

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC
          "-//SPRING//DTD BEAN//EN"
          "http://www.springframework.org/dtd/spring-beans.dtd">

          <beans>

          <!-- Bean configuration -->
          <bean id="businesslogicbean" class="org.springframework.aop.framework.ProxyFactoryBean">
           <property name="proxyInterfaces">
            <value>IBusinessLogic</value>
           </property>
           <property name="target">
            <ref local="beanTarget"/>
           </property>
           <property name="interceptorNames">
            <list>
             <value>theTracingBeforeAdvisor</value>
             <value>theTracingAfterAdvisor</value>
            </list>
           </property>
          </bean>
          <!-- Bean Classes -->
          <bean id="beanTarget"
          class="BusinessLogic"/>

          <!-- Advisor pointcut definition for before advice -->
          <bean id="theTracingBeforeAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
           <property name="advice">
            <ref local="theTracingBeforeAdvice"/>
           </property>
           <property name="pattern">
            <value>.*</value>
           </property>
          </bean>

          <!-- Advisor pointcut definition for after advice -->
          <bean id="theTracingAfterAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
           <property name="advice">
            <ref local="theTracingAfterAdvice"/>
           </property>
           <property name="pattern">
            <value>.*</value>
           </property>
          </bean>

          <!-- Advice classes -->
          <bean id="theTracingBeforeAdvice" class="TracingBeforeAdvice"/>
          <bean id="theTracingAfterAdvice" class="TracingAfterAdvice"/>
          </beans>

            theTracingBeforeAdvisor和theTracingAfterAdvisor advisor被添加到前面所聲明的businesslogicbean。每個advisor都可能截獲所有bean所關(guān)聯(lián)到的聯(lián)結(jié)點。Advisor本身就是bean,而它唯一的作用就是將切入點定義與通知bean關(guān)聯(lián)起來。本例中的切入點定義是在靜態(tài)對象層次結(jié)構(gòu)中指定相關(guān)聯(lián)結(jié)點的正則表達(dá)式。

            因為本例中使用了org.springframework.aop.support.RegexpMethodPointcutAdvisor切入點advisor,切入點邏輯是使用正則表達(dá)式指定的。正則表達(dá)式用于識別公有接口對IbusinessLogici接口的聯(lián)結(jié)點。下面是一些可以用來指定IBusinessLogic接口上的不同聯(lián)結(jié)點集合的正則表達(dá)式例子:

            .*:該表達(dá)式選擇advisor所關(guān)聯(lián)到的一個或多個bean上的所有聯(lián)結(jié)點。

            ./IBusinessLogic/.foo:該表達(dá)式只選擇IbusinessLogic接口上的foo()方法的聯(lián)結(jié)點。如果是advisor所關(guān)聯(lián)到的bean,則該表達(dá)式只選擇IBusinessLogic接口上的聯(lián)結(jié)點。

            springconfig.xml文件中最后的bean聲明指定實現(xiàn)通知bean的類。

            既然已經(jīng)指定了跟蹤方面的正確配置,那么下一次執(zhí)行MainApplication時,這些方面就會在初始化過程中被編織進去,而BusinessLogic bean中的所有方法都將被跟蹤,如圖2所示。





            圖2. 方法跟蹤方面應(yīng)用到BusinessLogic bean之后的順序圖


          方面的重用

            可以對方法跟蹤方面進行擴展,提供一個稍微復(fù)雜的記錄(Logging)方面。記錄方面提供了一個很不錯的重用例子,因為記錄方面所需的許多特性都已經(jīng)包含在方法跟蹤方面中了。

            在本例中,記錄方面擴展了方法跟蹤方面,以便顯示附加的與(在應(yīng)用程序的執(zhí)行過程中)所引發(fā)的異常有關(guān)的信息。

            要完全使用記錄方面,需要對應(yīng)用程序做一些更改。BusinessLogicException異常類提供了一個可以由IBusinessLogicInterface接口和BusinessLogic實現(xiàn)類新增的void bar()方法引發(fā)的異常。

          public class BusinessLogicException
          extends Exception
          {}

          public interface IBusinessLogic
          {
           public void foo();

           public void bar()
           throws BusinessLogicException;
          }

          public class BusinessLogic
          implements IBusinessLogic
          {
           public void foo()
           {
            System.out.println("Inside BusinessLogic.foo()");
           }

           public void bar()
           throws BusinessLogicException
           {
            System.out.println("Inside BusinessLogic.bar()");
            throw new BusinessLogicException();
           }
          }

            MainApplication類現(xiàn)在將對void bar()方法進行一次額外的調(diào)用,并處理選中的、可能由該方法引發(fā)的異常。

          import org.springframeworkcontext.ApplicationContext;
          import org.springframework.context.support.FileSystemXmlApplicationContext;

          public class MainApplication
          {
           public static void main(String [] args)
           {
            // Read the configuration file
            ApplicationContext ctx = new FileSystemXmlApplicationContext( "springconfig.xml");

            //Instantiate an object
            IBusinessLogic testObject =(IBusinessLogic) ctx.getBean("businesslogicbean");

            //Execute the public methods of the bean
            testObject.foo();

            try
            {
             testObject.bar();
            }
            catch(BusinessLogicException ble)
            {
             System.out.println( "Caught BusinessLogicException");
            }
           }
          }

            來自方法跟蹤方面的TracingBeforeAdvice和TracingAfterAdvice通知可以整體重用。LoggingThrowsAdvice類為新的異常記錄提供了通知。
          import org.springframework.aop.ThrowsAdvice;
          import java.lang.reflect.Method;

          public class LoggingThrowsAdvice
          implements ThrowsAdvice
          {
           public void afterThrowing(Method method,Object[] args,Object target,Throwable subclass)
           {
            System.out.println("Logging that a " +subclass +"Exception was thrown.");
           }
          }

            應(yīng)用記錄方面的最后一步是修改springconfig.xml配置文件,使其包含新添加的LoggingThrowsAdvice通知。

            圖3顯示了運行MainApplication并使用Spring框架應(yīng)用了記錄方面的UML順序圖。



            圖3. 記錄方面應(yīng)用到BusinessLogic bean之后的順序圖

            此處的記錄方面清楚地說明了如何重用現(xiàn)有方面以及如何在Spring框架中使用通知的throws形式。通過為before和after通知聲明新的通知來重寫現(xiàn)有的方法跟蹤方面實現(xiàn),可以實現(xiàn)更復(fù)雜的記錄方面,記錄到更復(fù)雜的記錄框架,比如LOG4J。

            結(jié)束語

            本文展示了使用Spring框架中的基本AOP結(jié)構(gòu)所應(yīng)用的一些簡單方面。在本系列的下一篇文章中,我們將介紹一些更實用的方面,探討方面的生命周期,使用Spring框架的around通知,并使用Spring來應(yīng)用AOP模式。



          posted on 2006-03-08 23:00 square 閱讀(131) 評論(0)  編輯  收藏

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


          網(wǎng)站導(dǎo)航:
           
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(2)

          隨筆檔案

          文章檔案

          收藏夾

          IBM developerworks JAVA

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 罗源县| 兴安盟| 合水县| 墨江| 南投市| 吐鲁番市| 鹤峰县| 新竹市| 十堰市| 屯门区| 阳高县| 武义县| 龙岩市| 田林县| 澄城县| 琼中| 银川市| 明星| 昌都县| 青铜峡市| 甘洛县| 阿瓦提县| 河源市| 连云港市| 葫芦岛市| 台中县| 赤壁市| 双城市| 庆阳市| 宜宾县| 张北县| 晋宁县| 淮北市| 涪陵区| 东乌珠穆沁旗| 建瓯市| 襄城县| 江油市| 福海县| 图木舒克市| 敦化市|