海水正藍(lán)

          面朝大海,春暖花開
          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 小胡子 閱讀(318) 評(píng)論(0)  編輯  收藏 所屬分類: AOP

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

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

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

          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è)試類

          /**
           * 代理測(cè)試類,使用代理
           *
           * 
          @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è)切面。在代理類中的sing(singname)方法是個(gè)后置處理方法。

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

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

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

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

          a、代理類:


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

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

              
          /**
               * 寫法固定,aop專用:綁定委托對(duì)象并返回一個(gè)代理類
               * 
               * 
          @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è)試類

          /**
           * 測(cè)試類
           * 
           * 
          @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è)代理類。ITalk iTalk = (ITalk) new DynamicProxy().bind(new PeopleTalk());  將業(yè)務(wù)接口和業(yè)務(wù)類綁定到動(dòng)態(tài)代理類。

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

          3、利用cglib

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

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


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

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

          }
          b、cglib代理類

          /**
           * 使用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(
          "事物開始");
                  result 
          = methodProxy.invokeSuper(proxy, args);
                  System.out.println(
          "事物結(jié)束");
                  
          return result;
              }

          }
          c.測(cè)試類

          /**
           * 測(cè)試類
           * 
           * 
          @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é)果:

          事物開始
          people talk業(yè)務(wù)方法
          事物結(jié)束
          事物開始
          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)航:
           
          主站蜘蛛池模板: 重庆市| 左权县| 循化| 望江县| 民丰县| 旌德县| 沂水县| 乃东县| 墨玉县| 浑源县| 寻甸| 澳门| 乡宁县| 洛阳市| 浠水县| 南岸区| 寿宁县| 东丰县| 岳西县| 临潭县| 宣威市| 信丰县| 林周县| 鹰潭市| 囊谦县| 上饶县| 黄大仙区| 长泰县| 从江县| 普兰店市| 贵南县| 屯留县| 万安县| 崇州市| 台北县| 抚宁县| 福州市| 象山县| 夏邑县| 常宁市| 鄢陵县|