Spring AOP介紹

          Posted on 2007-11-16 14:06 wigalos 閱讀(40111) 評論(14)  編輯  收藏

                 最近在學習spring,做了一些關(guān)于Spring AOP的總結(jié)和例子,參考書籍是李剛老師著的《輕量級J2EE企業(yè)應用實戰(zhàn)》。如下:

                                                       Spring AOP介紹

                 Spring的AOP是上面代理模式的深入。使用Spring AOP,開發(fā)者無需實現(xiàn)業(yè)務邏輯對象工廠,無需實現(xiàn)代理工廠,這兩個工廠都由Spring容器充當。Spring AOP不僅允許使用XML文件配置目標方法,ProxyHandler也允許使用依賴注入管理,Spring AOP提供了更多靈活的選擇。
          在下面Spring AOP的示例中,InvocationHandler采用動態(tài)配置,需要增加的方法也采用動態(tài)配置,一個目標對象可以有多個攔截器(類似于代理模式中的代理處理器)。
          下面是原始的目標對象:
          //目標對象的接口
          public interface  Person
          {
           //該接口聲明了兩個方法
           void info();
           void run();
          }
          下面是原始目標對象的實現(xiàn)類,實現(xiàn)類的代碼如下:
          //目標對象的實現(xiàn)類,實現(xiàn)類實現(xiàn)Person接口
          public class PersonImpl implements Person
          {
           //兩個成員屬性
           private String name;
           private int age;
           //name屬性的 setter方法
           public void setName(String name)
           {
            this.name = name;
           }
           //age屬性的setter方法
          public void setAge(int age)
           {
            this.age = age;
           }
           //info方法,該方法僅僅在控制臺打印一行字符串
           public void info()
           {
            System.out.println("我的名字是:  " + name + " , 今年年齡為:  " + age);
           }
           //run方法,該方法也在控制臺打印一行字符串。
           public void run()
           {
            if (age < 45)
            {
             System.out.println("我還年輕,奔跑迅速...");
            }
            else
            {
             System.out.println("我年老體弱,只能慢跑...");
            }
           }
          }
          該Person實例將由Spring容器負責產(chǎn)生和管理,name屬性和age屬性也采用依賴注入管理。
          為了充分展示Spring AOP的功能,此處為Person對象創(chuàng)建三個攔截器。第一個攔截器是調(diào)用方法前的攔截器,代碼如下:
          //調(diào)用目標方法前的攔截器,攔截器實現(xiàn)MethodBeforeAdvice接口
          public class MyBeforeAdvice implements MethodBeforeAdvice
          {
           //實現(xiàn)MethodBeforeAdvice接口,必須實現(xiàn)before方法,該方法將在目標
           //方法調(diào)用之前,自動被調(diào)用。
               public void before(Method m, Object[] args, Object target) throws Throwable
           {
            System.out.println("方法調(diào)用之前...");
            System.out.println("下面是方法調(diào)用的信息:");
            System.out.println("所執(zhí)行的方法是:" + m);
            System.out.println("調(diào)用方法的參數(shù)是:" + args);
            System.out.println("目標對象是:" + target);
               }
          }
          第二個攔截器是方法調(diào)用后的攔截器,該攔截器將在方法調(diào)用結(jié)束后自動被調(diào)用,攔截器代碼如下:
          //調(diào)用目標方法后的攔截器,該攔截器實現(xiàn)AfterReturningAdvice接口
          public class MyAfterAdvice implements AfterReturningAdvice
          {
           //實現(xiàn)AfterReturningAdvice接口必須實現(xiàn)afterReturning方法,該方法將在目標方法
           //調(diào)用結(jié)束后,自動被調(diào)用。
               public void afterReturning(Object returnValue, Method m, Object[] args, Object target)throws Throwable
           {
            System.out.println("方法調(diào)用結(jié)束...");
          System.out.println("目標方法的返回值是 : " + returnValue);
            System.out.println("目標方法是 : " + m);
            System.out.println("目標方法的參數(shù)是 : " + args);
            System.out.println("目標對象是 : " + target);
              }
          }
          第三個攔截器是是Around攔截器,該攔截器既可以在目標方法之前調(diào)用,也可以在目標方法調(diào)用之后被調(diào)用。下面是Around攔截器的代碼:
          //Around攔截器實現(xiàn)MethodInterceptor接口
          public class MyAroundInterceptor implements MethodInterceptor
          {
           //實現(xiàn)MethodInterceptor接口必須實現(xiàn)invoke方法
               public Object invoke(MethodInvocation invocation) throws Throwable
           {
            //調(diào)用目標方法之前執(zhí)行的動作
                   System.out.println("調(diào)用方法之前: invocation對象:[" + invocation + "]");
            //調(diào)用目標方法
                   Object rval = invocation.proceed();
            //調(diào)用目標方法之后執(zhí)行的動作
                   System.out.println("調(diào)用結(jié)束...");
                   return rval;
              }
          }
          利用Spring AOP框架,實現(xiàn)之前的代理模式相當簡單。只需要實現(xiàn)對應的攔截器即可,無需創(chuàng)建自己的代理工廠,只需采用Spring容器作為代理工廠。下面在Spring配置文件中配置目標bean,以及攔截器。
          下面是Spring配置文件的代碼:
          <?xml version="1.0" encoding="gb2312"?>
          <!--  Spring配置文件的文件頭-->
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
           "http://www.springframework.org/dtd/spring-beans.dtd">
          <!--  Spring配置文件的根元素-->
          <beans>
           <!--  配置目標對象-->
           <bean id="personTarget" class="lee.PersonImpl">
            <!--  為目標對象注入name屬性值-->
            <property name="name">
             <value>Wawa</value>
            </property>
            <!--  為目標對象注入age屬性值-->
            <property name="age">
             <value>51</value>
            </property>
           </bean>
           <!--  第一個攔截器-->
           <bean id="myAdvice" class="lee.MyBeforeAdvice"/>
           <!--  第二個攔截器-->
           <bean id="myAroundInterceptor" class="lee.MyAroundInterceptor"/>
          <!--  將攔截器包裝成Advisor,該對象還確定代理對怎樣的方法增加處理-->
           <bean id="runAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
            <!--  advice屬性確定處理bean-->
            <property name="advice">
             <!-- 此處的處理bean定義采用嵌套bean,也可引用容器的另一個bean-->
             <bean class="lee.MyAfterAdvice"/>
            </property>
            <!--  patterns確定正則表達式模式-->
            <property name="patterns">
             <list>
              <!--  確定正則表達式列表-->
              <value>.*run.*</value>
             </list>
            </property>
           </bean>
           <!--  使用ProxyFactoryBean 產(chǎn)生代理對象-->
           <bean id="person" class="org.springframework.aop.framework.ProxyFactoryBean">
            <!--  代理對象所實現(xiàn)的接口-->
            <property name="proxyInterfaces">
             <value>lee.Person</value>
            </property>
            <!--  設(shè)置目標對象-->
            <property name="target">
             <ref local="personTarget"/>  
            </property>
            <!--  代理對象所使用的攔截器-->
            <property name="interceptorNames">
             <list>
              <value>runAdvisor</value>
              <value>myAdvice</value>
              <value>myAroundInterceptor</value>
             </list>
            </property>
           </bean>
          </beans>
          該配置文件使用ProxyFactoryBean來生成代理對象,配置ProxyFactoryBean工廠bean時,指定了target屬性,該屬性值就是目標對象,該屬性值為personTarget,指定代理的目標對象為personTarget。通過interceptorNames屬性確定代理需要的攔截器,攔截器可以是普通的Advice,普通Advice將對目標對象的所有方法起作用,攔截器也可以是Advisor,Advisor是Advice和切面的組合,用于確定目標對象的哪些方法需要增加處理,以及怎樣的處理。在上面的配置文件中,使用了三個攔截器,其中myAdvice、myAroundInterceptor都是普通Advice,它們將對目標對象的所有方法起作用。而runAdvisor則使用了正則表達式切面,匹配run方法,即該攔截器只對目標對象的run方法起作用。

          下面是測試代理的主程序:
          public class BeanTest
          {
              public static void main(String[] args)throws Exception
          {
            //創(chuàng)建Spring容器
          ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
            //獲取代理對象
            Person p = (Person)ctx.getBean("person");
            //執(zhí)行info方法
            p.info();
                   System.out.println("===========================================");
            //執(zhí)行run方法
            p.run();
              }
          }
          下面是程序的執(zhí)行結(jié)果:
          方法調(diào)用之前...
          下面是方法調(diào)用的信息:
          所執(zhí)行的方法是:public abstract void lee.Person.info()
          調(diào)用方法的參數(shù)是:null
          目標對象是:lee.PersonImpl@b23210
          調(diào)用方法之前: invocation對象:[invocation: method 'info', arguments
          []; target is of class [lee.PersonImpl]]
          我的名字是:  Wawa , 今年年齡為:  51
          調(diào)用結(jié)束...
          ===========================================
          方法調(diào)用之前...
          下面是方法調(diào)用的信息:
          所執(zhí)行的方法是:public abstract void lee.Person.run()
          調(diào)用方法的參數(shù)是:null
          目標對象是:lee.PersonImpl@b23210
          調(diào)用方法之前: invocation對象:[invocation: method 'run', arguments [
          ]; target is of class [lee.PersonImpl]]
          我年老體弱,只能慢跑...
          調(diào)用結(jié)束...
          方法調(diào)用結(jié)束...
          目標方法的返回值是 : null
          目標方法是 : public abstract void lee.Person.run()
          目標方法的參數(shù)是 : null
          目標對象是 : lee.PersonImpl@b23210
          程序的執(zhí)行結(jié)果中一行“=”用于區(qū)分兩次調(diào)用的方法。在調(diào)用info方法時,只有myAdvice和myAroundInterceptor兩個攔截器起作用,調(diào)用run方法時候,三個攔截器都起作用了。

                 通過上面的介紹,可看出Spring的AOP框架是對代理模式簡化,并拓展了代理模式的使用。
          Spring AOP是Spring聲明式事務的基礎(chǔ)。了解Spring AOP對深入理解Spring的聲明式事務管理是非常有好處的。Spring AOP還可以完成很多功能,例如基于AOP的權(quán)限檢查。

           

          Feedback

          # re: Spring AOP介紹  回復  更多評論   

          2008-06-11 16:32 by 路過
          不錯

          # re: Spring AOP介紹  回復  更多評論   

          2008-12-17 14:06 by javaTom
          很好,很強打!
          謝謝

          # re: Spring AOP介紹  回復  更多評論   

          2009-03-27 17:22 by 羅技
          很差!

          # re: Spring AOP介紹[未登錄]  回復  更多評論   

          2010-12-10 11:15 by y
          很詳細

          # re: Spring AOP介紹  回復  更多評論   

          2011-03-04 13:41 by minJack
          謝謝樓主.

          # re: Spring AOP介紹  回復  更多評論   

          2012-02-06 10:52 by zyh
          言簡意賅 很棒

          # re: Spring AOP介紹[未登錄]  回復  更多評論   

          2012-02-24 09:57 by june
          通俗易懂,謝謝

          # re: Spring AOP介紹  回復  更多評論   

          2012-05-02 18:01 by ityangba
          要是能排下版就好,看著太費勁了

          # re: Spring AOP介紹  回復  更多評論   

          2012-11-23 15:03 by yryyr
          ryry

          # re: Spring AOP介紹  回復  更多評論   

          2013-01-11 13:56 by xm

          # re: Spring AOP介紹  回復  更多評論   

          2013-07-16 15:48 by zhong2lian
          @路過
          程序你運行了嗎?難道測試程序獲取的那個bean 能切入嗎?

          # re: Spring AOP介紹  回復  更多評論   

          2013-07-19 11:37 by www.dsprint.cn(武漢畫冊)
          還不錯

          # re: Spring AOP介紹  回復  更多評論   

          2013-07-19 11:41 by www.dsprint.cn(武漢印刷)
          nobad

          # re: Spring AOP介紹  回復  更多評論   

          2013-07-19 14:13 by www.dsprint.cn(武漢印刷)
          很好

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


          網(wǎng)站導航:
           
          主站蜘蛛池模板: 石林| 同德县| 高清| 佛山市| 平定县| 迭部县| 富源县| 青海省| 修武县| 正宁县| 荃湾区| 杭锦后旗| 都昌县| 古田县| 西吉县| 常州市| 多伦县| 农安县| 北宁市| 锡林郭勒盟| 新邵县| 舟山市| 泰来县| 青河县| 卓尼县| 明光市| 长子县| 东阿县| 二连浩特市| 安国市| 长宁县| 朔州市| 合山市| 宁武县| 汤阴县| 合水县| 屯门区| 娄底市| 通海县| 喜德县| 白银市|