1. 程式人生 > >由事務註解引起的代理相關

由事務註解引起的代理相關

void isa val 行修改 java動態代理 個性 織入 nsa tproxy

事務註解是通過spring aop代理實現

大致步驟是:
1、caller -》 aop 代理對象
2、aop代理對象的事務增強
3、代理interceptor 其他增強
4、執行目標對象的目標方法
5、按照4-》1 返回

代理:
aop代理 AopUtils.isAopProxy(bean)
cglib代理 AopUtils.isCglibProxy(bean)
java動態代理 AopUtils.isJdkDynamicProxy(bean)

問題:

    public interface TestServiceImpl implements TestService{
        @Transactional
        public void a(){
            this.b();
        }
        @Transactional
        public void b(){

        }
    }
當a中調用b時,b的事務沒有執行,因為a調用b直接走步驟4,而不是通過aop代理的方式

解決方法:
調用方法改為:aopProxy.b();

1.通過ThreadLocal方法暴露Aop代理對象
    <aop:aspectj-autoproxy expose-proxy="true"/>
2.this.b()  ---->     ((TestService)AopContext.currentProxy()).b();

其他方法:
1、將本身註入;或者 實現BeanPostProcessor 接口實現自身代理對象的註入;
註解:將本身註入的方式不適用於循環依賴的兩個對象,如果循環依賴,註入的可能不是代理對象,而是目標對象本身,達不到代理的目的;

AOP 相關

1、問題
針對同一類方法增加 同一類的日誌記錄、監控、安全監測等

2、解決方法
2.1 直接增加在方法裏;--- 重復,緊耦合
2.2 抽象類共性設計,子類個性化設計;--- 一榮俱榮一損俱損
2.3 裝飾器/代理模式設計;--- 緊耦合,每個實現類需要一個代理對象
2.4 動態代理(不適用於final類)

    2.4.1 java動態代理---接口
             @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
                Object retVal = null;
                boolean ok = true;
                // 代理方法之前的處理:條件判斷,日誌,權限等
                if (!ok) {
                    throw new RuntimeException("權限等");
                } else {
                    // 反射調用目標對象的方法
                    method.invoke(target, args);
                }
                // 此處可以是 目標對象方法之後的後處理
                return retVal;
            }
    2.4.2 cglib動態代理---接口和類
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object resVal = null;
                /**
                 * 預處理
                 */
                boolean ok = true;
                if (!ok) {
                    throw new RuntimeException("沒有權限");
                } else {
                    resVal = methodProxy.invoke(target, objects);
                }
                /**
                 * 代理後處理
                 */
                return resVal;
            }
    動態代理本質:對目標對象增強;
    代理限制:只能在父類方法調用之前或之後進行增強,不能在中間進行修改,想要在中間進行修改,需要ASM(java 字節碼生成庫);

2.5 Aop 代理
        @Aspect
        public class AopTest {
            @Pointcut(value = "execution(* *(..))")
            public void pointCut() {}
    
            @Around(value = "pointCut()")
            public Object around(ProceedingJoinPoint pjp) throws Throwable {
                Object retVal = null;
                /**
                 * 前置處理...
                 */
                retVal = pjp.proceed();
                /**
                 * 後置處理...
                 */
                return retVal;
            }
        }
    AOP缺點:依賴aop框架;

3、aop 關註點.
關註點:所關註的任何東西;-- 需要被增強的各種方法;
關註點分離:將問題劃分為不可分割的單獨部分,單一獨立的模塊;
橫切點分離:會在多個模塊中出現,跨越多個模塊;一定要獨立,松耦合,可以隨意組合使用。
織入:橫切點分離之後,需要通過某種技術,將很切點融入到系統中,以完成需要的功能,因此需要織入。織入可能在編譯期、加載器或運行期等進行。

AOP 關註與業務無關,但是卻被各模塊公用的邏輯或功能,例如,日誌管理、權限控制、事務處理等,封裝起來,減少重復代碼,減少模塊之間的耦合度。

AOP代理(AOP Proxy):
AOP框架使用代理模式創建的對象,從而實現在連接點處插入增強(即應用切面),就是通過代理來對目標對象應用切面。在Spring中,AOP代理可以用JDK動態代理或CGLIB代理實現,而通過攔截器模型應用切面。默認使用jdk動態代理。

IOC/DI

- IOC (inversion of control)控制反轉
    定義:控制權從應用轉移到框架(實現了IOC思想的容器成為IOC容器)

    對象的創建過程:
        1、創建對象
        2、實例化(主動、被動)
        3、依賴關系 (直接、間接)
        4、裝配 (主動、被動)
    創建可以由應用程序主動進行,完成1-4;也可以將2-4交由框架進行,使用的時候框架已經準備好了,可以直接使用;
    對象創建的控制權轉移到了框架,這就是IOC。
    ==> 建立a對象,需要b屬性,則通過反射創建b對象,裝配到a對象中。

    ps:容器提供組件運行環境 + 管理組件生命周期
    IOC容器=容器+依賴裝配

- DI(Dependency Injection)依賴註入
    用一個單獨的對象(裝配器IOC容器)來裝配對象之間的依賴關系。
    註入方式:構造器註入、setter方式註入、接口註入等。

備註:IOC/DI 的開發思路
    1、應用程序不主動創建對象,但需要描述創建他們的方式;
    2、應用程序不直接進行服務的裝配,但需要配置文件描述組件和服務的依賴關系,容器會自動裝配他們。
    原理:基於好萊塢原則--別來找我,我會去找你。也就是所有的組件都是被動的,組件的創建和裝配都有容器來管理。

由事務註解引起的代理相關