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

CGLIB 動態代理實戰:無需接口的高性能代碼生成庫

     編輯:Java 綜合教學

核心原理

  • 基於 ASM 字節碼操作框架,運行時動態生成子類
  • 通過繼承目標類、重寫方法實現攔截
  • 無需目標類實現接口,補足 JDK 動態代理短板
  • 廣泛用於 Spring AOP、Hibernate 等框架

核心 API

類/接口作用
Enhancer代理創建核心類,設置父類與回調
MethodInterceptor攔截接口,intercept() 定義增強邏輯
MethodProxy代理方法調用,invokeSuper() 調用父類方法

基礎示例:自定義攔截器

public class MyMethodInterceptor implements MethodInterceptor {
    public String myFun(String arg) { return "hello, " + arg; }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) 
            throws Throwable {
        System.out.println("[intercept] before");
        String result = (String) args[0] + "...";
        System.out.println("[intercept] after");
        return result;  // 直接返回,不調用父類方法
    }

    public Object createProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyMethodInterceptor.class);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    public static void main(String[] args) {
        MyMethodInterceptor target = new MyMethodInterceptor();
        MyMethodInterceptor proxy = (MyMethodInterceptor) target.createProxy();
        proxy.myFun("cglib test");  // 觸發攔截
    }
}

通用工具類:Spring 風格封裝

public class MyCGLIBProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class<?> clazz) {
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) 
            throws Throwable {
        System.out.println("cglib before action");
        Object result = proxy.invokeSuper(o, args);  // 調用目標方法
        System.out.println("cglib after action");
        return result;
    }
}

使用方式

MyCGLIBProxy p = new MyCGLIBProxy();
Performer proxy = (Performer) p.getProxy(TargetClass.class);
proxy.perform();  // 自動觸發 before/after

CGLIB vs JDK 動態代理

維度JDK ProxyCGLIB
前提條件目標類實現接口無需接口,繼承目標類
生成類型實現接口的匿名類目標類的子類
final 方法可代理無法代理(無法重寫)
性能(舊版)反射調用較慢FastClass 機制較快
性能(JDK 8+)Lambda/MethodHandle 優化差距縮小

適用場景

  • 第三方庫類無接口、需增強
  • Spring AOP 默認策略:有接口用 JDK,無接口用 CGLIB
  • 需代理具體類而非接口的場景
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved