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

Spring AOP 核心基石:靜態代理、動態代理與 CGLIB 深度解析

     編輯:Java 綜合教學

Spring AOP 核心基石:靜態代理、動態代理與 CGLIB 深度解析

代理模式是 Spring AOP 的實現基礎。本文通過安全檢查的業務場景,層層遞進講解靜態代理、JDK 動態代理與 CGLIB 代理的實現原理與代碼實踐。

業務場景:用戶管理的安全攔截

定義用戶管理接口 UserManager 及實現類 UserManagerImpl。需求:在每個業務方法執行前進行安全檢查,但不想污染業務邏輯代碼。

一、靜態代理:手工編寫代理類

創建實現同一接口的代理類 UserManagerImplProxy,持有目標對象引用,在代理方法中織入橫切邏輯:

public class UserManagerImplProxy implements UserManager {
    private UserManager userManager;  // 目標對象引用

    public UserManagerImplProxy(UserManager userManager) {
        this.userManager = userManager;
    }

    public void checkSecurity() {
        System.out.println("--------安全檢查----------");
    }

    @Override
    public void addUser(String username, String password) {
        checkSecurity();  // 橫切邏輯
        this.userManager.addUser(username, password);  // 委託目標對象
    }
    // 其他方法同理...
}

缺點:接口方法一多,代理類代碼膨脹,維護成本高,這正是 AOP 自動化代理要解決的問題。

二、JDK 動態代理:運行時生成代理

核心是實現 InvocationHandler 接口,利用 Proxy.newProxyInstance 動態生成代理對象:

public class SecurityHandler implements InvocationHandler {
    private Object targetObject;

    public Object newProxy(Object targetObject) {
        this.targetObject = targetObject;
        return Proxy.newProxyInstance(
            targetObject.getClass().getClassLoader(),
            targetObject.getClass().getInterfaces(),
            this
        );
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        checkSecurity();  // 統一攔截點
        return method.invoke(targetObject, args);  // 反射調用目標方法
    }
}

優勢:一個處理器類處理所有接口方法,靈活控制是否啟用攔截邏輯。限制:目標類必須實現接口。

三、CGLIB 代理:繼承實現無接口代理

針對無接口的類,CGLIB 通過繼承目標類並重寫方法實現代理:

public class CGlibProxyFactory implements MethodInterceptor {
    private Object targetObject;

    public Object newProxy(Object targetObject) {
        this.targetObject = targetObject;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetObject.getClass());  // 設置父類
        enhancer.setCallback(this);  // 設置攔截器
        return enhancer.create();  // 生成代理對象
    }

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        checkSecurity();
        return method.invoke(targetObject, args);
    }
}

關鍵差異:JDK 代理基於接口(組合模式),CGLIB 基於繼承(繼承模式),無法代理 final 類/方法。

總結對比

代理方式實現機制適用場景性能特點
靜態代理手工編寫類簡單、固定場景無額外開銷
JDK 動態代理接口+反射目標實現接口調用較快,生成較慢
CGLIB 代理繼承+FastClass無接口/補強場景生成較快,調用極快

Spring AOP 默認優先使用 JDK 動態代理,目標類無接口時回退到 CGLIB。理解三者原理,有助於排查代理失效、事務不生效等經典問題。

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