海水正藍(lán)

          面朝大海,春暖花開(kāi)
          posts - 145, comments - 29, trackbacks - 0, articles - 1
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          日歷

          <2013年3月>
          242526272812
          3456789
          10111213141516
          17181920212223
          24252627282930
          31123456

          文章檔案

          搜索

          •  

          【轉(zhuǎn)】理解AOP

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

          Aspect Oriented Programming  面向切面編程。解耦是程序員編碼開(kāi)發(fā)過(guò)程中一直追求的。AOP也是為了解耦所誕生。

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

          AOP 在Spring框架中被作為核心組成部分之一,的確Spring將AOP發(fā)揮到很強(qiáng)大的功能。最常見(jiàn)的就是事務(wù)控制。工作之余,對(duì)于使用的工具,不免需要了解其所以然。學(xué)習(xí)了一下,寫(xiě)了些程序幫助理解。

          AOP 主要是利用代理模式的技術(shù)來(lái)實(shí)現(xiàn)的。

          1、靜態(tài)代理:就是設(shè)計(jì)模式中的proxy模式

          a、業(yè)務(wù)接口


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

              
          public void talk(String msg);

          }
          b、業(yè)務(wù)實(shí)現(xiàn)

          /**
           * 真實(shí)主題角色:定義真實(shí)的對(duì)象。
           * 
           * 
          @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、代理對(duì)象

          /**
           * 代理主題角色:內(nèi)部包含對(duì)真實(shí)主題的引用,并且提供和真實(shí)主題角色相同的接口。
           * 
           * 
          @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、測(cè)試類(lèi)

          /**
           * 代理測(cè)試類(lèi),使用代理
           *
           * 
          @author yanbin
           * 
           
          */
          public class ProxyPattern {

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

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

          }

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

          這樣就實(shí)現(xiàn)了,其他的輔助方法和業(yè)務(wù)方法的解耦。業(yè)務(wù)不需要專(zhuān)門(mén)去調(diào)用,而是走到talk方法,順理成章的調(diào)用sing方法

          再?gòu)倪@段代碼看:1、要實(shí)現(xiàn)代理方式,必須要定義接口。2、每個(gè)業(yè)務(wù)類(lèi),需要一個(gè)代理類(lèi)。

          2、動(dòng)態(tài)代理:jdk1.5中提供,利用反射。實(shí)現(xiàn)InvocationHandler接口。

          業(yè)務(wù)接口還是必須得,業(yè)務(wù)接口,業(yè)務(wù)類(lèi)同上。

          a、代理類(lèi):


          /**
           * 動(dòng)態(tài)代理類(lèi)
           * 
           * 
          @author yanbin
           * 
           
          */
          public class DynamicProxy implements InvocationHandler {

              
          /** 需要代理的目標(biāo)類(lèi) */
              
          private Object target;

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

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

          }
          b、測(cè)試類(lèi)

          /**
           * 測(cè)試類(lèi)
           * 
           * 
          @author yanbin
           * 
           
          */
          public class Test {

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

          輸出結(jié)果會(huì)是:

          切面之前執(zhí)行
          people talk業(yè)務(wù)說(shuō)法
          切面之后執(zhí)行

          說(shuō)明只要在業(yè)務(wù)調(diào)用方法切面之前,是可以動(dòng)態(tài)的加入需要處理的方法。

          從代碼來(lái)看,如果再建立一個(gè)業(yè)務(wù)模塊,也只需要一個(gè)代理類(lèi)。ITalk iTalk = (ITalk) new DynamicProxy().bind(new PeopleTalk());  將業(yè)務(wù)接口和業(yè)務(wù)類(lèi)綁定到動(dòng)態(tài)代理類(lèi)。

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

          3、利用cglib

          CGLIB是針對(duì)類(lèi)來(lái)實(shí)現(xiàn)代理的,他的原理是對(duì)指定的目標(biāo)類(lèi)生成一個(gè)子類(lèi),并覆蓋其中方法實(shí)現(xiàn)增強(qiáng)。采用的是繼承的方式。不細(xì)說(shuō),看使用

          a、業(yè)務(wù)類(lèi)


          /**
           * 業(yè)務(wù)類(lèi)
           * 
           * 
          @author yanbin
           * 
           
          */
          public class PeopleTalk {

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

          }
          b、cglib代理類(lèi)

          /**
           * 使用cglib動(dòng)態(tài)代理
           * 
           * 
          @author yanbin
           * 
           
          */
          public class CglibProxy implements MethodInterceptor {

              
          private Object target;

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

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

          }
          c.測(cè)試類(lèi)

          /**
           * 測(cè)試類(lèi)
           * 
           * 
          @author yanbin
           * 
           
          */
          public class Test {

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

          }

          最后輸出結(jié)果:

          事物開(kāi)始
          people talk業(yè)務(wù)方法
          事物結(jié)束
          事物開(kāi)始
          spreak chinese業(yè)務(wù)方法
          事物結(jié)束

          由于篇幅有限,這篇主要對(duì)AOP的原理簡(jiǎn)單實(shí)現(xiàn)做了演示和闡述,有助自己理解。至于Spring的AOP實(shí)現(xiàn)上面無(wú)外乎其右,不過(guò)實(shí)現(xiàn)方面復(fù)雜的多。

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






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


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 霍邱县| 长丰县| 澳门| 汝南县| 梓潼县| 肃北| 宜良县| 西丰县| 诏安县| 汝城县| 太湖县| 河南省| 京山县| 桐庐县| 利川市| 普陀区| 柏乡县| 福泉市| 昌都县| 沁阳市| 介休市| 安仁县| 乌拉特后旗| 淅川县| 辽中县| 沂南县| 彭水| 福建省| 白玉县| 安达市| 陆丰市| 晋宁县| 新乐市| 当涂县| 岳阳市| 宁都县| 鱼台县| 江孜县| 乃东县| 临武县| 章丘市|