熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

對spring的aop理解

2022-06-13   來源: Java開源技術 
    問題
    問題想要添加日志記錄性能監控安全監測
    最初解決方案
    最初解決方案
 
    缺點太多重復代碼且緊耦合
    抽象類進行共性設計子類進行個性設計此處不講解缺點一榮俱榮一損俱損
    使用裝飾器模式/代理模式改進的解決方案
    裝飾器模式動態地給一個對象添加一些額外的職責就增加功能來說 裝飾器模式相比生成子類更為靈活



    代理模式為其他對象提供一種代理以控制對這個對象的訪問
 
 
    缺點緊耦合每個業務邏輯需要一個裝飾器實現或代理
   


    JDK動態代理解決方案(比較通用的解決方案)
    Java代碼
    public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
    thistarget = target;
    }
    @Override
    public Object invoke(Object proxy Method method Object[] args) throws Throwable {
    //記錄日志 時間統計開始 安全檢查
    Object retVal = methodinvoke(target args)
    //時間統計結束
    return retVal;
    }
    public static Object proxy(Object target) {
    return ProxynewProxyInstance(targetgetClass()getClassLoader()
    targetgetClass()getInterfaces() new MyInvocationHandler(target))
    }
    }
    [java]
    public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
    thistarget = target;
    }
    @Override
    public Object invoke(Object proxy Method method Object[] args) throws Throwable {
    //記錄日志    時間統計開始      安全檢查
    Object retVal = methodinvoke(target args)
    //時間統計結束
    return retVal;
    }
    public static Object proxy(Object target) {
    return ProxynewProxyInstance(targetgetClass()getClassLoader()
    targetgetClass()getInterfaces() new MyInvocationHandler(target))
    }
    }
    編程模型
    Java代碼
    //proxy 在其上調用方法的代理實例
    //method 攔截的方法
    //args 攔截的參數
    Override
    public Object invoke(Object proxy Method method Object[] args) throws Throwable {
    Object retVal=null;
    //預處理
    //前置條件判斷
    boolean ok = true;
    if(!ok) {//不滿足條件
    throw new RuntimeException(你沒有權限
    }
    else {//反射調用目標對象的某個方法
    retVal = methodinvoke(target args)
    }
    //後處理
    return retVal;
    }
    [java]
    //proxy     在其上調用方法的代理實例
    //method 攔截的方法
    //args       攔截的參數
    Override
    public Object invoke(Object proxy Method method Object[] args) throws Throwable {
    Object retVal=null;
    //預處理
    //前置條件判斷
    boolean ok = true;
    if(!ok) {//不滿足條件
    throw new RuntimeException(你沒有權限
    }
    else {//反射調用目標對象的某個方法
    retVal = methodinvoke(target args)
    }
    //後處理
    return retVal;
    }
    缺點使用麻煩不能代理類只能代理接口
    CGLIB動態代理解決方案(比較通用的解決方案)
    Java代碼
    public class MyInterceptor implements MethodInterceptor {
    private Object target;
    public MyInterceptor(Object target) {
    thistarget = target;
    }
    @Override
    public Object intercept(Object proxy Method method Object[] args
    MethodProxy invocation) throws Throwable {
    //記錄日志 時間統計開始 安全檢查
    Object retVal = invocationinvoke(target args)
    //時間統計結束
    return retVal;
    }
    public static Object proxy(Object target) {
    return Enhancercreate(targetgetClass() new MyInterceptor(target))
    }
    }
    [java]
    public class MyInterceptor implements MethodInterceptor  {
    private Object target;
    public MyInterceptor(Object target) {
    thistarget = target;
    }
    @Override
    public Object intercept(Object proxy Method method Object[] args
    MethodProxy invocation) throws Throwable {
    //記錄日志 時間統計開始   安全檢查
    Object retVal = invocationinvoke(target args)
    //時間統計結束
    return retVal;
    }
    public static Object proxy(Object target) {
    return Enhancercreate(targetgetClass() new MyInterceptor(target))
    }
    }
    編程模型
    Java代碼
    //proxy 在其上調用方法的代理實例 method攔截的方法 args 攔截的參數
    //invocation 用來去調用被代理對象方法的
    @Override
    public Object intercept(Object proxy Method method Object[] args
    MethodProxy invocation) throws Throwable {
    //預處理
    //前置條件判斷
    boolean ok = true;
    if(!ok) {//不滿足條件
    throw new RuntimeException(出錯了
    }
    else {//調用目標對象的某個方法
    Object retVal = invocationinvoke(target args)
    }
    //後處理
    return retVal;
    }
    [java]
    //proxy 在其上調用方法的代理實例    method攔截的方法    args  攔截的參數
    //invocation 用來去調用被代理對象方法的
    @Override
    public Object intercept(Object proxy Method method Object[] args
    MethodProxy invocation) throws Throwable {
    //預處理
    //前置條件判斷
    boolean ok = true;
    if(!ok) {//不滿足條件
    throw new RuntimeException(出錯了
    }
    else {//調用目標對象的某個方法
    Object retVal = invocationinvoke(target args)
    }
    //後處理
    return retVal;
    }
    優點能代理接口和類
    缺點使用麻煩不能代理final類
    動態代理本質
    本質對目標對象增強
    最終表現為類(動態創建子類)看手工生成(子類)還是自動生成(子類)
    代理限制
    只能在父類方法被調用之前或之後進行增強(功能的修改)不能在中間進行修改要想在方法調用中增強需要ASM(java 字節碼生成庫)
    其他動態代理框架
    jboss:javassist (hibernate 中默認為javassist)
    (hibernate 之前中默認為cglib)
 






    AOP解決方案(通用且簡單的解決方案)
    Java代碼
    @Aspect
    public class PayEbiAspect {
    @Pointcut(value=execution(* pay())
    public void pointcut() {}
    @Around(value=pointcut()
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
    //記錄日志
    //時間統計開始
    //安全檢查
    Object retVal = pjpproceed()//調用目標對象的真正方法
    //時間統計結束
    return retVal;
    }
    }
    [java]
    @Aspect
    public class PayEbiAspect {
    @Pointcut(value=execution(* pay())
    public void pointcut() {}
    @Around(value=pointcut()
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
    //記錄日志
    //時間統計開始
    //安全檢查
    Object retVal = pjpproceed()//調用目標對象的真正方法
    //時間統計結束
    return retVal;
    }
    }
    編程模型
    Java代碼
    // 切入點
    @Pointcut(value=execution(* *())
    public void pointcut() {}
    // 攔截器的interceptor
    @Around(value=pointcut()
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
    Object retVal=null;
    //預處理
    //前置條件判斷
    boolean ok = true;
    if(!ok) {//不滿足條件
    throw new RuntimeException(你沒有權限
    }
    else {//調用目標對象的某個方法
    retVal = pjpproceed()
    }
    //後處理
    return retVal;
    }
    [java]
    // 切入點
    @Pointcut(value=execution(* *())
    public void pointcut() {}
    // 攔截器的interceptor
    @Around(value=pointcut()
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
    Object retVal=null;
    //預處理
    //前置條件判斷
    boolean ok = true;
    if(!ok) {//不滿足條件
    throw new RuntimeException(你沒有權限
    }
    else {//調用目標對象的某個方法
    retVal = pjpproceed()
    }
    //後處理
    return retVal;
    }
    缺點依賴AOP框架
    AOP入門
    概念
    n關注點可以認為是所關注的任何東西比如上邊的支付組件
    n關注點分離將問題細化為單獨部分即可以理解為不可再分割的組件如上邊的日志組件和支付組件
    n橫切關注點會在多個模塊中出現使用現有的編程方法橫切關注點會橫越多個模塊結果是使系統難以設計理解實現和演進如日志組件橫切於支付組件
    織入橫切關注點分離後需要通過某種技術將橫切關注點融合到系統中從而完成需要的功能因此需要織入織入可能在編譯期加載期運行期等進行
    nAOP是什麼(Aspect Oriented Programming)
    AOP是一種編程范式提供從另一個角度來考慮程序結構以完善面向對象編程(OOP)
    AOP為開發者提供了一種描述橫切關注點的機制並能夠自動將橫切關注點織入到面向對象的軟件系統中從而實現了橫切關注點的模塊化
    AOP能夠將那些與業務無關卻為業務模塊所共同調用的邏輯或責任例如事務處理日志管理權限控制等封裝起來便於減少系統的重復代碼降低模塊間的耦合度並有利於未來的可操作性和可維護性
    nAOP能干什麼也是AOP帶來的好處
    :降低模塊的耦合度
    :使系統容易擴展
    :設計決定的遲綁定使用AOP設計師可以推遲為將來的需求作決定因為它
    可以把這種需求作為獨立的方面很容易的實現
    :更好的代碼復用性
 
   AOP基本概念
    連接點(Joinpoint)
    表示需要在程序中插入橫切關注點的擴展點連接點可能是類初始化方法執行方法調用字段調用或處理異常等等Spring只支持方法執行連接點在AOP中表示為在哪裡做;
    切入點(Pointcut)
    選擇一組相關連接點的模式即可以認為連接點的集合Spring支持perl正則表達式和AspectJ切入點模式Spring默認使用AspectJ語法在AOP中表示為在哪裡做的集合;
    增強(Advice)或稱為增強
    在連接點上執行的行為增強提供了在AOP中需要在切入點所選擇的連接點處進行擴展現有行為的手段包括前置增強(before advice)後置增強 (after advice)環繞增強 (around advice)在Spring中通過代理模式實現AOP並通過攔截器模式以環繞連接點的攔截器鏈織入增強 ;在AOP中表示為做什麼;
    方面/切面(Aspect)
    橫切關注點的模塊化比如上邊提到的日志組件可以認為是增強引入和切入點的組合在Spring中可以使用Schema和@AspectJ方式進行組織實現在AOP中表示為在哪裡做和做什麼集合;
    目標對象(Target Object)
    需要被織入橫切關注點的對象即該對象是切入點選擇的對象需要被增強的對象從而也可稱為被增強對象;由於Spring AOP 通過代理模式實現從而這個對象永遠是被代理對象在AOP中表示為對誰做;
    AOP代理(AOP Proxy)
    AOP框架使用代理模式創建的對象從而實現在連接點處插入增強(即應用切面)就是通過代理來對目標對象應用切面在Spring中AOP代理可以用JDK動態代理或CGLIB代理實現而通過攔截器模型應用切面
    織入(Weaving)
    織入是一個過程是將切面應用到目標對象從而創建出AOP代理對象的過程織入可以在編譯期類裝載期運行期進行



    引入(intertype declaration)
    也稱為內部類型聲明為已有的類添加額外新的字段或方法Spring允許引入新的接口(必須對應一個實現)到所有被代理對象(目標對象) 在AOP中表示為做什麼(新增什麼);
    AOP的Advice類型
    前置增強(Before advice)
    在某連接點之前執行的增強但這個增強不能阻止連接點前的執行(除非它拋出一個異常)
    後置返回增強(After returning advice)
    在某連接點正常完成後執行的增強例如一個方法沒有拋出任何異常正常返回
    後置異常增強(After throwing advice)
    在方法拋出異常退出時執行的增強
    後置最終增強(After (finally) advice)
    當某連接點退出的時候執行的增強(不論是正常返回還是異常退出)
    環繞增強(Around Advice)
    包圍一個連接點的增強如方法調用這是最強大的一種增強類型 環繞增強可以在方法調用前後完成自定義的行為它也會選擇是否繼續執行連接點或直接返回它們自己的返回值或拋出異常來結束執行
 
 
 


From:http://tw.wingwit.com/Article/program/Java/ky/201311/27884.html
    推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.