首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring AOP 實現原理深度解析:從靜態代理到動態代理的演進

     編輯:Java 相關知識

AOP 核心概念

AOP(面向切面編程)是 OOP 的補充。OOP 適合縱向關係(繼承),而橫切關係(日誌、事務、安全、緩存)分散在各業務模組中,導致代碼重複、耦合度高。AOP 通過「橫切」技術將這些通用行為封裝為可重用模組(切面),降低耦合,提升可維護性。

  • 核心關注點:業務主流程
  • 橫切關注點:權限驗證、日誌記錄、事務管理等

手寫 AOP 框架演進過程

階段一:靜態代理

代理類與目標類實現同一介面,代理持有目標引用。缺點:每個目標類都需編寫專屬代理類,代碼膨脹。

public class ProxyHello implements IHello {
    private IHello target;
    public ProxyHello(IHello target) { this.target = target; }
    public void sayHello(String str) {
        Logger.start();      // 前置增強
        target.sayHello(str);
        Logger.end();        // 後置增強
    }
}

階段二:JDK 動態代理

利用 java.lang.reflect.InvocationHandler 與 Proxy.newProxyInstance() 在運行時動態生成代理類。單一代理類可服務多個目標類(需實現介面)。

public class DynamicProxy implements InvocationHandler {
    private Object target;
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Logger.start();              // 前置增強
        Object result = method.invoke(target, args); // 執行目標方法
        Logger.end();                // 後置增強
        return result;
    }
}

階段三:解耦增強邏輯(引入切面介面)

將「前置/後置增強」抽象為介面,代理類通過反射動態調用切面實現,實現代理邏輯與業務增強完全解耦。這就是 Spring AOP 的雛形。

public interface IAdvice { void before(Method m); void after(Method m); }

public class LoggingAdvice implements IAdvice { ... }

public class GenericProxy implements InvocationHandler {
    private Object target, advice;
    public Object bind(Object target, Object advice) { ... }
    public Object invoke(Object proxy, Method method, Object[] args) {
        Method before = advice.getClass().getMethod("before", Method.class);
        before.invoke(advice, method);
        Object result = method.invoke(target, args);
        Method after = advice.getClass().getMethod("after", Method.class);
        after.invoke(advice, method);
        return result;
    }
}

階段四:引入 Pointcut(切點)與配置文件

  • 在 invoke() 中根據方法名判斷是否應用增強
  • 方法名模式配置在 XML 中,實現聲明式配置

Spring AOP 核心組件對應關係

手寫框架概念Spring AOP 術語說明
目標對象Target Object被代理的業務對象
InvocationHandler 實現類MethodInterceptor環繞通知,核心攔截鏈
IAdvice 介面Advice (Before/After/Around)具體增強邏輯
方法名匹配邏輯Pointcut切點表達式定義攔截位置
Proxy.bind()ProxyFactoryBean / @EnableAspectJAutoProxy代理創建與織入

JDK 動態代理 vs CGLIB

  • JDK:基於介面,生成實現目標介面的匿名類。目標類必須實現介面。
  • CGLIB:基於繼承,生成目標類的子類,重寫非 final 方法。不需要介面,但無法代理 final 類/方法。

Spring 默認:有介面用 JDK,無介面用 CGLIB。可通過 proxy-target-class="true" 強制使用 CGLIB。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved