CGlib實現原理詳解

一、CGlib代理原理

在面向對象編程中,代理模式是一種常用的設計模式。它可以在不改變原有對象代碼的前提下,通過新增代理對象,在代理對象中增加一些其他的功能,從而提供更加完整、更加複雜的功能。CGlib代理是基於動態代理的一種實現方式,是Java中常用的代理技術之一。

動態代理和靜態代理最大的區別就在於代理類的生成方式。靜態代理需要人工編寫代理類,而動態代理則可以在運行時動態生成代理類。Java JDK提供了一個Proxy類,可以通過Proxy的工廠方法newProxyInstance動態生成代理對象。

不過JDK提供的動態代理有一個限制,就是只能代理實現了接口的類。如果要代理沒有實現接口的類,就要使用其他的代理技術。而CGlib是一種可以代理類的技術。使用CGlib實現動態代理,本質上是在運行時,通過位元組碼處理框架ASM,動態生成一個被代理類的子類,並覆蓋其中的方法,達到代理的目的。

二、CGlib原理

CGlib,全稱為Code Generation Library,是一個開源的非侵入式的Java位元組碼生成庫。它允許在運行時對位元組碼進行操作,生成新的類,以實現例如AOP之類的功能。

與靜態代理和JDK動態代理不同,CGlib在運行時動態生成被代理類的子類,並重寫其中的方法。因此,對被代理類的方法訪問是通過子類方法訪問的,而不是被代理類方法訪問的。子類方法可以通過調用父類方法實現對被代理類方法的訪問。

CGlib生成子代理類的方式是在內存中構建代理類的所有方法的位元組碼,並將其轉換成class對象,從而實現對被代理類方法的代理。由於CGlib是直接操作class位元組碼實現代理的,因此需要引入ASM位元組碼框架,用於處理Java位元組碼。

三、CGlib底層原理

CGlib底層運用Java位元組碼技術實現代理,下面簡單介紹一下Java位元組碼的執行過程:

一是Java程序源代碼被編譯成Java位元組碼文件(.class文件)。

二是Java虛擬機(JVM)將Java位元組碼文件解釋成機器指令。

三是CPU執行機器指令,進行計算操作。

CGlib底層實現通過ASM技術直接操作位元組碼來完成對代理對象的生成,主要分為以下幾個步驟:

1、確定需要代理的類和方法,生成對應的MethodInterceptor實現類。

public class UserProxy implements MethodInterceptor {
    private Object target;
    public UserProxy(Object target) {
        this.target = target;
    }
    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method invoke");
        Object result = method.invoke(target, args);
        System.out.println("After method invoke");
        return result;
    }
}

2、使用ASM庫加載被代理類的位元組碼,並動態生成代理對象的子類。

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new UserProxy(target));
Object proxy = enhancer.create();

在這個過程中,我們需要在內存中先讀取被代理類的二進制位元組碼文件,然後再解析出類信息,這個時候我們就要使用ASM庫:

ClassReader classReader = new ClassReader(target.getClass().getName());
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
ClassVisitor classVisitor = new AddFieldAdapter(classWriter,
                Opcodes.ACC_PUBLIC, "hash", "I");
classReader.accept(classVisitor, ClassReader.SKIP_DEBUG);
byte[] data = classWriter.toByteArray();

四、CGlib底層實現原理

底層實現原理主要是通過ASM(a very small and fast Java bytecode manipulation framework)框架來直接操作數據位元組碼。ASM可以直接生成和修改位元組碼,也可以在位元組碼的生成和修改中提供一些幫助和支持。

ASM使用Visitor模式來操作位元組碼,它通過ClassVisitor和MethodVisitor類提供了訪問類層次結構和方法級別元素的途徑。

CGlib實現動態代理的過程如下:

1、創建Enhancer對象。

2、設置父類和回調方法。

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new UserServiceInterceptor());

3、通過Enhancer對象的create()方法生成代理對象。

UserServiceImpl proxyUserService = (UserServiceImpl) enhancer.create();

4、調用代理對象方法。

String username = userSerivceimpl.getUserName();

五、CGlib動態代理原理

CGlib可以創建一個類的子類,並且在子類中採用方法攔截的技術攔截所有父類方法的調用。在攔截器中可以添加一些額外的邏輯。相比Java動態代理,CGlib不要求被代理類必須實現接口,它是基於類代理,對指定的類生成一個子類,並覆蓋其中的方法來實現代理的功能。

在使用CGlib進行代理時,代理類和被代理類構成了繼承關係。代理類繼承被代理類,所以代理類擁有了被代理類的所有屬性和方法,而且可以攔截被代理方法進行增強。

下面是一個CGlib動態代理實現的示例代碼:

public class UserServiceInterceptor implements MethodInterceptor {
    private UserService userService;
    public UserServiceInterceptor(UserService userService) {
        this.userService = userService;
    }
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("begin method...");
        Object result = method.invoke(userService, objects);
        System.out.println("end method...");
        return result;
    }
}
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class); 
enhancer.setCallback(new UserServiceInterceptor(userService));
UserService userServiceProxy = (UserService) enhancer.create();

結束語

CGlib是一種非常常用的代理方式,通過位元組碼的修改,可以實現對被代理對象的增強和功能擴展。在使用CGlib進行代理時,我們需要深入了解其實現原理,靈活運用其底層知識,才能更好地發揮其代理作用。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/307349.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2025-01-02 18:06
下一篇 2025-01-02 18:06

相關推薦

  • Harris角點檢測算法原理與實現

    本文將從多個方面對Harris角點檢測算法進行詳細的闡述,包括算法原理、實現步驟、代碼實現等。 一、Harris角點檢測算法原理 Harris角點檢測算法是一種經典的計算機視覺算法…

    編程 2025-04-29
  • 瘦臉算法 Python 原理與實現

    本文將從多個方面詳細闡述瘦臉算法 Python 實現的原理和方法,包括該算法的意義、流程、代碼實現、優化等內容。 一、算法意義 隨着科技的發展,瘦臉算法已經成為了人們修圖中不可缺少…

    編程 2025-04-29
  • 神經網絡BP算法原理

    本文將從多個方面對神經網絡BP算法原理進行詳細闡述,並給出完整的代碼示例。 一、BP算法簡介 BP算法是一種常用的神經網絡訓練算法,其全稱為反向傳播算法。BP算法的基本思想是通過正…

    編程 2025-04-29
  • GloVe詞向量:從原理到應用

    本文將從多個方面對GloVe詞向量進行詳細的闡述,包括其原理、優缺點、應用以及代碼實現。如果你對詞向量感興趣,那麼這篇文章將會是一次很好的學習體驗。 一、原理 GloVe(Glob…

    編程 2025-04-27
  • 編譯原理語法分析思維導圖

    本文將從以下幾個方面詳細闡述編譯原理語法分析思維導圖: 一、語法分析介紹 1.1 語法分析的定義 語法分析是編譯器中將輸入的字符流轉換成抽象語法樹的一個過程。該過程的目的是確保輸入…

    編程 2025-04-27
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分佈式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25
  • Java BigDecimal 精度詳解

    一、基礎概念 Java BigDecimal 是一個用於高精度計算的類。普通的 double 或 float 類型只能精確表示有限的數字,而對於需要高精度計算的場景,BigDeci…

    編程 2025-04-25

發表回復

登錄後才能評論