海水正藍

          面朝大海,春暖花開
          posts - 145, comments - 29, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          【轉】理解AOP

          Posted on 2013-03-02 22:28 小胡子 閱讀(315) 評論(0)  編輯  收藏 所屬分類: AOP

          Aspect Oriented Programming  面向切面編程。解耦是程序員編碼開發過程中一直追求的。AOP也是為了解耦所誕生。

          具體思想是:定義一個切面,在切面的縱向定義處理方法,處理完成之后,回到橫向業務流。

          AOP 在Spring框架中被作為核心組成部分之一,的確Spring將AOP發揮到很強大的功能。最常見的就是事務控制。工作之余,對于使用的工具,不免需要了解其所以然。學習了一下,寫了些程序幫助理解。

          AOP 主要是利用代理模式的技術來實現的。

          1、靜態代理:就是設計模式中的proxy模式

          a、業務接口


          /**
           * 抽象主題角色:聲明了真實主題和代理主題的共同接口。
           * 
           * 
          @author yanbin
           * 
           
          */
          public interface ITalk {

              
          public void talk(String msg);

          }
          b、業務實現

          /**
           * 真實主題角色:定義真實的對象。
           * 
           * 
          @author yanbin
           * 
           
          */
          public class PeopleTalk implements ITalk {

              
          public String username;
              
          public String age;

              
          public PeopleTalk(String username, String age) {
                  
          this.username = username;
                  
          this.age = age;
              }

              
          public void talk(String msg) {
                  System.out.println(msg 
          + "!你好,我是" + username + ",我年齡是" + age);
              }

              
          public String getName() {
                  
          return username;
              }

              
          public void setName(String name) {
                  
          this.username = name;
              }

              
          public String getAge() {
                  
          return age;
              }

              
          public void setAge(String age) {
                  
          this.age = age;
              }

          }
          c、代理對象

          /**
           * 代理主題角色:內部包含對真實主題的引用,并且提供和真實主題角色相同的接口。
           * 
           * 
          @author yanbin
           * 
           
          */
          public class TalkProxy implements ITalk {

              
          private ITalk talker;

              
          public TalkProxy(ITalk talker) {
                  
          // super();
                  this.talker = talker;
              }

              
          public void talk(String msg) {
                  talker.talk(msg);
              }

              
          public void talk(String msg, String singname) {
                  talker.talk(msg);
                  sing(singname);
              }

              
          private void sing(String singname) {
                  System.out.println(
          "唱歌:" + singname);
              }

          }
          d、測試類

          /**
           * 代理測試類,使用代理
           *
           * 
          @author yanbin
           * 
           
          */
          public class ProxyPattern {

              
          public static void main(String[] args) {
                  
          // 不需要執行額外方法的。
                  ITalk people = new PeopleTalk("AOP""18");
                  people.talk(
          "No ProXY Test");
                  System.out.println(
          "-----------------------------");

                  
          // 需要執行額外方法的(切面)
                  TalkProxy talker = new TalkProxy(people);
                  talker.talk(
          "ProXY Test""代理");
              }

          }

          從這段代碼可以看出來,代理模式其實就是AOP的雛形。 上端代碼中talk(String msg, String singname)是一個切面。在代理類中的sing(singname)方法是個后置處理方法。

          這樣就實現了,其他的輔助方法和業務方法的解耦。業務不需要專門去調用,而是走到talk方法,順理成章的調用sing方法

          再從這段代碼看:1、要實現代理方式,必須要定義接口。2、每個業務類,需要一個代理類。

          2、動態代理:jdk1.5中提供,利用反射。實現InvocationHandler接口。

          業務接口還是必須得,業務接口,業務類同上。

          a、代理類:


          /**
           * 動態代理類
           * 
           * 
          @author yanbin
           * 
           
          */
          public class DynamicProxy implements InvocationHandler {

              
          /** 需要代理的目標類 */
              
          private Object target;

              
          /**
               * 寫法固定,aop專用:綁定委托對象并返回一個代理類
               * 
               * 
          @param delegate
               * 
          @return
               
          */
              
          public Object bind(Object target) {
                  
          this.target = target;
                  
          return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
              }

              
          /**
               * 
          @param Object
               *            target:指被代理的對象。
               * 
          @param Method
               *            method:要調用的方法
               * 
          @param Object
               *            [] args:方法調用時所需要的參數
               
          */
              @Override
              
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                  Object result 
          = null;
                  
          // 切面之前執行
                  System.out.println("切面之前執行");
                  
          // 執行業務
                  result = method.invoke(target, args);
                  
          // 切面之后執行
                  System.out.println("切面之后執行");
                  
          return result;
              }

          }
          b、測試類

          /**
           * 測試類
           * 
           * 
          @author yanbin
           * 
           
          */
          public class Test {

              
          public static void main(String[] args) {
                  
          // 綁定代理,這種方式會在所有的方法都加上切面方法
                  ITalk iTalk = (ITalk) new DynamicProxy().bind(new PeopleTalk());
                  iTalk.talk(
          "業務說明");
              }
          }

          輸出結果會是:

          切面之前執行
          people talk業務說法
          切面之后執行

          說明只要在業務調用方法切面之前,是可以動態的加入需要處理的方法。

          從代碼來看,如果再建立一個業務模塊,也只需要一個代理類。ITalk iTalk = (ITalk) new DynamicProxy().bind(new PeopleTalk());  將業務接口和業務類綁定到動態代理類。

          但是這種方式:還是需要定義接口。

          3、利用cglib

          CGLIB是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現增強。采用的是繼承的方式。不細說,看使用

          a、業務類


          /**
           * 業務類
           * 
           * 
          @author yanbin
           * 
           
          */
          public class PeopleTalk {

              
          public void talk(String msg) {
                  System.out.println(
          "people talk" + msg);
              }

          }
          b、cglib代理類

          /**
           * 使用cglib動態代理
           * 
           * 
          @author yanbin
           * 
           
          */
          public class CglibProxy implements MethodInterceptor {

              
          private Object target;

              
          /**
               * 創建代理對象
               * 
               * 
          @param target
               * 
          @return
               
          */
              
          public Object getInstance(Object target) {
                  
          this.target = target;
                  Enhancer enhancer 
          = new Enhancer();
                  enhancer.setSuperclass(
          this.target.getClass());
                  
          // 回調方法
                  enhancer.setCallback(this);
                  
          // 創建代理對象
                  return enhancer.create();
              }

              @Override
              
          public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                  Object result 
          = null;
                  System.out.println(
          "事物開始");
                  result 
          = methodProxy.invokeSuper(proxy, args);
                  System.out.println(
          "事物結束");
                  
          return result;
              }

          }
          c.測試類

          /**
           * 測試類
           * 
           * 
          @author yanbin
           * 
           
          */
          public class Test {

              
          public static void main(String[] args) {
                  PeopleTalk peopleTalk 
          = (PeopleTalk) new CglibProxy().getInstance(new PeopleTalk());
                  peopleTalk.talk(
          "業務方法");
                  peopleTalk.spreak(
          "業務方法");
              }

          }

          最后輸出結果:

          事物開始
          people talk業務方法
          事物結束
          事物開始
          spreak chinese業務方法
          事物結束

          由于篇幅有限,這篇主要對AOP的原理簡單實現做了演示和闡述,有助自己理解。至于Spring的AOP實現上面無外乎其右,不過實現方面復雜的多。

          原文出自:
          http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html






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


          網站導航:
           
          主站蜘蛛池模板: 开封市| 松溪县| 凤庆县| 沾化县| 海安县| 丹巴县| 眉山市| 北宁市| 安西县| 磴口县| 确山县| 马关县| 砚山县| 亚东县| 东城区| 张家口市| 武强县| 墨玉县| 开阳县| 灵山县| 张家港市| 屏东市| 远安县| 孝义市| 筠连县| 德惠市| 惠水县| 朝阳县| 通城县| 台中县| 青冈县| 大竹县| 和硕县| 庄河市| 武陟县| 平江县| 息烽县| 黔江区| 聂拉木县| 漾濞| 府谷县|