我的家園

          我的家園

          我對AOP的理解

          Posted on 2012-04-15 16:37 zljpp 閱讀(137) 評論(0)  編輯  收藏

          1、問題?


          問題:想要添加日志記錄、性能監(jiān)控、安全監(jiān)測?

          ?

          2、最初解決方案?

          2.1、最初解決方案

          缺點:太多重復(fù)代碼,且緊耦合

          ?

          2.2、抽象類進行共性設(shè)計,子類進行個性設(shè)計,此處不講解,缺點一榮俱榮,一損俱損

          ?

          2.3、使用裝飾器模式/代理模式改進的解決方案

          裝飾器模式:動態(tài)地給一個對象添加一些額外的職責(zé)。就增加功能來說, 裝飾器模式相比生成子類更為靈活。
          代理模式:為其他對象提供一種代理以控制對這個對象的訪問。


          ?
          缺點:緊耦合,每個業(yè)務(wù)邏輯需要一個裝飾器實現(xiàn)或代理

          2.4、JDK動態(tài)代理解決方案(比較通用的解決方案)?
          public class MyInvocationHandler implements InvocationHandler { 
              private Object target;
              public MyInvocationHandler(Object target) {
                  this.target = target;
              }
              @Override
              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                  //1.記錄日志    2.時間統(tǒng)計開始      3.安全檢查
                  Object retVal = method.invoke(target, args);
                  //4.時間統(tǒng)計結(jié)束
                  return retVal;   
              }
              public static Object proxy(Object target) {
                  return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                          target.getClass().getInterfaces(), new MyInvocationHandler(target));
              }
          }
          

          ?編程模型?

             //proxy     在其上調(diào)用方法的代理實例 
             //method 攔截的方法
             //args       攔截的參數(shù)
             Override
              public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                  Object retVal=null;
                  //預(yù)處理
                  //前置條件判斷
                  boolean ok = true;        
                  if(!ok) {//不滿足條件
                      throw new RuntimeException("你沒有權(quán)限");
                  }
                  else {//反射調(diào)用目標對象的某個方法
                      retVal = method.invoke(target, args);
                  }
                  //后處理
                  return retVal;
              }
           ?

          缺點:使用麻煩,不能代理類,只能代理接口??

          ?

          CGLIB動態(tài)代理解決方案(比較通用的解決方案)
          public class MyInterceptor implements MethodInterceptor  {	
              private Object target;
              public MyInterceptor(Object target) {
                  this.target = target;
              }
              @Override
              public Object intercept(Object proxy, Method method, Object[] args, 
                                                   MethodProxy invocation) throws Throwable {
                  //1.記錄日志 2.時間統(tǒng)計開始   3.安全檢查
                  Object retVal = invocation.invoke(target, args);
                  //4.時間統(tǒng)計結(jié)束
                  return retVal;   
              }
              public static Object proxy(Object target) {
                  return Enhancer.create(target.getClass(), new MyInterceptor(target));
              }
          }

          ?編程模型

           //proxy 在其上調(diào)用方法的代理實例    method攔截的方法    args  攔截的參數(shù)
           //invocation 用來去調(diào)用被代理對象方法的
          @Override
          public Object intercept(Object proxy, Method method, Object[] args, 
                                                 MethodProxy invocation) throws Throwable {
              //預(yù)處理
              //前置條件判斷
              boolean ok = true;        
              if(!ok) {//不滿足條件
                  throw new RuntimeException("出錯了");
              }
              else {//調(diào)用目標對象的某個方法
                  Object retVal = invocation.invoke(target, args);
              }
              //后處理
              return retVal;
          }
          優(yōu)點:能代理接口和類
          缺點:使用麻煩,不能代理final

          ?

          動態(tài)代理本質(zhì)?

          本質(zhì):對目標對象增強
          ???????????最終表現(xiàn)為類(動態(tài)創(chuàng)建子類),看手工生成(子類)還是自動生成(子類)
          代理限制:
          ???????????只能在父類方法被調(diào)用之前或之后進行增強(功能的修改),不能在中間進行修改,要想在方法調(diào)用中增強,需要ASM(java?字節(jié)碼生成庫)
          其他動態(tài)代理框架
          jbossjavassist?hibernate 3.3中默認為javassist
          ???????????????????????????(hibernate 3.3之前中默認為cglib

          ?


          ?
          2.5、AOP解決方案(通用且簡單的解決方案)
          @Aspect
          public class PayEbiAspect {    
              @Pointcut(value="execution(* pay(..))")
              public void pointcut() {}
              @Around(value="pointcut()")
              public Object around(ProceedingJoinPoint pjp) throws Throwable {
                  //1.記錄日志
                  //2.時間統(tǒng)計開始
                  //3.安全檢查
                  Object retVal = pjp.proceed();//調(diào)用目標對象的真正方法
                  //4.時間統(tǒng)計結(jié)束
                  return retVal;
              }
          }
          編程模型
              //2 切入點
              @Pointcut(value="execution(* *(..))")
              public void pointcut() {}
              //3 攔截器的interceptor
              @Around(value="pointcut()")
              public Object around(ProceedingJoinPoint pjp) throws Throwable {
                  Object retVal=null;
                  //預(yù)處理
                  //前置條件判斷
                  boolean ok = true;
                  if(!ok) {//不滿足條件
                     throw new RuntimeException("你沒有權(quán)限");
                  }
                  else {//調(diào)用目標對象的某個方法
                       retVal = pjp.proceed(); 
                  }
                  //后處理
                  return retVal;
              }
          
          ?
          缺點:依賴AOP框架?

          AOP入門
          概念:
          n關(guān)注點:可以認為是所關(guān)注的任何東西,比如上邊的支付組件;
          n關(guān)注點分離:將問題細化為單獨部分,即可以理解為不可再分割的組件,如上邊的日志組件和支付組件;
          n橫切關(guān)注點:會在多個模塊中出現(xiàn),使用現(xiàn)有的編程方法,橫切關(guān)注點會橫越多個模塊,結(jié)果是使系統(tǒng)難以設(shè)計、理解、實現(xiàn)和演進,如日志組件橫切于支付組件。
          織入:橫切關(guān)注點分離后,需要通過某種技術(shù)將橫切關(guān)注點融合到系統(tǒng)中從而完成需要的功能,因此需要織入,織入可能在編譯期、加載期、運行期等進行。

          nAOP是什么(Aspect?? Oriented?? Programming)
          ?AOP是一種編程范式,提供從另一個角度來考慮程序結(jié)構(gòu)以完善面向?qū)ο缶幊?/span>(OOP)。
          ?AOP為開發(fā)者提供了一種描述橫切關(guān)注點的機制,并能夠自動將橫切關(guān)注點織入到面向?qū)ο蟮能浖到y(tǒng)中,從而實現(xiàn)了橫切關(guān)注點的模塊化。
          ?AOP能夠?qū)⒛切┡c業(yè)務(wù)無關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責(zé)任,例如事務(wù)處理、日志管理、權(quán)限控制等,封裝起來,便于減少系統(tǒng)的重復(fù)代碼,降低模塊間的耦合度,并有利于未來的可操作性和可維護性。
          nAOP能干什么,也是AOP帶來的好處
          1:降低模塊的耦合度
          2:使系統(tǒng)容易擴展
          3:設(shè)計決定的遲綁定:使用AOP,設(shè)計師可以推遲為將來的需求作決定,因為它
          可以把這種需求作為獨立的方面很容易的實現(xiàn)。
          4:更好的代碼復(fù)用性

          ?
          AOP基本概念
          ?連接點(Joinpoint):
          ??? 表示需要在程序中插入橫切關(guān)注點的擴展點,連接點可能是類初始化、方法執(zhí)行、方法調(diào)用、字段調(diào)用或處理異常等等,Spring只支持方法執(zhí)行連接點,AOP中表示在哪里做
          切入點(Pointcut):
          ??? 選擇一組相關(guān)連接點的模式,即可以認為連接點的集合,Spring支持perl5正則表達式和AspectJ切入點模式,Spring默認使用AspectJ語法,AOP中表示為在哪里做的集合
          增強(Advice):或稱為增強
          ??? 在連接點上執(zhí)行的行為,增強提供了在AOP中需要在切入點所選擇的連接點處進行擴展現(xiàn)有行為的手段;包括前置增強(before advice)、后置增強?(after advice)、環(huán)繞增強?(around advice),在Spring中通過代理模式實現(xiàn)AOP,并通過攔截器模式以環(huán)繞連接點的攔截器鏈織入增強?;AOP中表示為做什么
          方面/切面(Aspect):
          ????? 橫切關(guān)注點的模塊化,比如上邊提到的日志組件。可以認為是增強、引入和切入點的組合;在Spring中可以使用Schema@AspectJ方式進行組織實現(xiàn);AOP中表示為在哪里做和做什么集合
          目標對象(Target Object):
          ??? 需要被織入橫切關(guān)注點的對象,即該對象是切入點選擇的對象,需要被增強的對象,從而也可稱為“被增強對象”;由于Spring AOP?通過代理模式實現(xiàn),從而這個對象永遠是被代理對象,AOP中表示為對誰做
          AOP代理(AOP Proxy):
          ??? AOP框架使用代理模式創(chuàng)建的對象,從而實現(xiàn)在連接點處插入增強(即應(yīng)用切面),就是通過代理來對目標對象應(yīng)用切面。在Spring中,AOP代理可以用JDK動態(tài)代理或CGLIB代理實現(xiàn),而通過攔截器模型應(yīng)用切面。
          織入(Weaving):
          ??? 織入是一個過程,是將切面應(yīng)用到目標對象從而創(chuàng)建出AOP代理對象的過程,織入可以在編譯期、類裝載期、運行期進行。
          引入(inter-type declaration):
          ??? 也稱為內(nèi)部類型聲明,為已有的類添加額外新的字段或方法,Spring允許引入新的接口(必須對應(yīng)一個實現(xiàn))到所有被代理對象(目標對象),?AOP中表示為做什么(新增什么)

          AOP的Advice類型
          前置增強(Before advice):
          ??? 在某連接點之前執(zhí)行的增強,但這個增強不能阻止連接點前的執(zhí)行(除非它拋出一個異常)。
          后置返回增強(After returning advice):
          ??? 在某連接點正常完成后執(zhí)行的增強:例如,一個方法沒有拋出任何異常,正常返回。
          后置異常增強(After throwing advice):
          ??? 在方法拋出異常退出時執(zhí)行的增強。
          后置最終增強(After (finally) advice):
          ??? 當(dāng)某連接點退出的時候執(zhí)行的增強(不論是正常返回還是異常退出)。
          環(huán)繞增強Around Advice):
          ??? 包圍一個連接點的增強,如方法調(diào)用。這是最強大的一種增強類型。 環(huán)繞增強可以在方法調(diào)用前后完成自定義的行為。它也會選擇是否繼續(xù)執(zhí)行連接點或直接返回它們自己的返回值或拋出異常來結(jié)束執(zhí)行。


          ?
          AOP開發(fā)步驟
          ? 類似于IoC/DI容器開發(fā)步驟,需要描述哪個連接點需要哪個通用功能(增強

          橫切關(guān)注點的表現(xiàn)有:  
            ·代碼糾結(jié)/混亂——當(dāng)一個模塊或代碼段同時管理多個關(guān)注點時發(fā)生這種情況。 
            ·代碼分散——當(dāng)一個關(guān)注點分布在許多模塊中并且未能很好地局部化和模塊化時發(fā)生這種情況 。
          AOP包括三個清晰的開發(fā)步驟:
          1功能橫切:找出橫切關(guān)注點。
          2實現(xiàn)分離:各自獨立的實現(xiàn)這些橫切關(guān)注點所需要完成的功能。
          3功能回貼:在這一步里,方面集成器通過創(chuàng)建一個模塊單元——?方面來指定重組的規(guī)則。重組過程——也叫織入或結(jié)合——?則使用這些信息來構(gòu)建最終系統(tǒng)。

          推薦閱讀書籍:
          AspectJ in Action

          AOSD中文版--基于用例的面向方面軟件開發(fā)



          推薦閱讀的帖子:

          ?


          文章主要是為了拋磚引玉,希望有更多牛人的指點。



          已有 0 人發(fā)表留言,猛擊->>這里<<-參與討論


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


          網(wǎng)站導(dǎo)航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 杭锦旗| 城固县| 上蔡县| 油尖旺区| 杨浦区| 基隆市| 奉节县| 锡林郭勒盟| 彰化市| 沭阳县| 湘乡市| 乌兰察布市| 汉川市| 南澳县| 玉门市| 定西市| 简阳市| 松潘县| 南漳县| 西平县| 乌拉特中旗| 嘉峪关市| 息烽县| 石门县| 阿拉善左旗| 正定县| 合江县| 金坛市| 元阳县| 鄂州市| 崇文区| 临邑县| 繁峙县| 驻马店市| 娄烦县| 界首市| 新化县| 寻甸| 砀山县| 安溪县| 荆州市|