欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot項目中JDK動態(tài)代理和CGLIB動態(tài)代理的使用詳解

 更新時間:2025年03月11日 08:57:24   作者:冰糖心書房  
JDK動態(tài)代理和CGLIB動態(tài)代理都是SpringBoot中實現(xiàn)AOP的重要技術,JDK動態(tài)代理通過反射生成代理類,適用于目標類實現(xiàn)了接口的場景,性能較好,易用性高,但必須實現(xiàn)接口且不能代理final方法,CGLIB動態(tài)代理通過生成子類實現(xiàn)代理

在 Spring Boot 項目中,JDK 動態(tài)代理和 CGLIB 動態(tài)代理都是實現(xiàn) AOP (面向切面編程) 的重要技術。 它們的主要區(qū)別在于代理對象的生成方式和適用范圍。

下面詳細介紹它們的使用場景:

1. JDK 動態(tài)代理 (JDK Dynamic Proxy)

原理:

  • JDK 動態(tài)代理是 Java 提供的內置代理機制,它通過反射在運行時動態(tài)地生成代理類。
  • 代理類會實現(xiàn)目標類實現(xiàn)的接口,并將接口中的方法調用委托給一個 InvocationHandler 對象來處理。
  • InvocationHandler 接口負責實現(xiàn)具體的增強邏輯,例如日志記錄、安全檢查、事務管理等。

使用場景:

  • 目標類實現(xiàn)了接口: 如果目標類實現(xiàn)了接口,則 Spring AOP 默認使用 JDK 動態(tài)代理。
  • 簡單 AOP 場景: 適用于簡單的 AOP 場景,例如只需要對接口方法進行增強的情況。
  • 不需要代理類的構造函數(shù): JDK 動態(tài)代理創(chuàng)建代理對象時,不需要調用目標類的構造函數(shù)。

優(yōu)點:

  • 簡單易用: JDK 動態(tài)代理是 Java 內置的代理機制,使用起來比較簡單。
  • 不需要第三方庫: 不需要依賴第三方庫。
  • 對接口友好: 代理類實現(xiàn)了目標類實現(xiàn)的接口,符合面向接口編程的思想。

缺點:

  • 必須實現(xiàn)接口: 目標類必須實現(xiàn)接口,否則無法使用 JDK 動態(tài)代理。
  • 只能代理接口方法: 只能代理接口中定義的方法,無法代理類自身定義的方法。

示例代碼:

// 接口
interface MyInterface {
    void doSomething();
}

// 實現(xiàn)類
class MyClass implements MyInterface {
    @Override
    public void doSomething() {
        System.out.println("MyClass is doing something...");
    }
}

// 調用處理器
class MyInvocationHandler implements InvocationHandler {
    private Object target; // 被代理的對象

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before method: " + method.getName()); // 前置增強
        Object result = method.invoke(target, args); // 調用原始方法
        System.out.println("After method: " + method.getName()); // 后置增強
        return result;
    }
}

// 使用 JDK 動態(tài)代理
public class JDKDynamicProxyExample {
    public static void main(String[] args) {
        MyInterface target = new MyClass(); // 創(chuàng)建目標對象
        MyInvocationHandler handler = new MyInvocationHandler(target); // 創(chuàng)建調用處理器

        // 創(chuàng)建代理對象
        MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
                MyInterface.class.getClassLoader(),
                new Class[] {MyInterface.class},
                handler
        );

        proxy.doSomething(); // 調用代理對象的方法,會被攔截
    }
}

2. CGLIB 動態(tài)代理 (CGLIB Dynamic Proxy)

原理:

  • CGLIB (Code Generation Library) 是一個強大的、高性能的代碼生成庫。
  • CGLIB 動態(tài)代理通過在運行時動態(tài)地生成目標類的子類來實現(xiàn)代理。
  • 代理類會繼承目標類,并重寫目標類的方法,在重寫的方法中實現(xiàn)增強邏輯。
  • CGLIB 動態(tài)代理不需要目標類實現(xiàn)接口,可以直接代理類。

使用場景:

  • 目標類沒有實現(xiàn)接口: 如果目標類沒有實現(xiàn)接口,則 Spring AOP 使用 CGLIB 動態(tài)代理。
  • 需要代理類自身定義的方法: 需要代理類自身定義的方法,而不僅僅是接口方法。
  • 需要更高的性能: 在某些情況下,CGLIB 動態(tài)代理的性能可能比 JDK 動態(tài)代理更好。

優(yōu)點:

  • 不需要實現(xiàn)接口: 目標類不需要實現(xiàn)接口,可以直接代理類。
  • 可以代理類自身定義的方法: 可以代理類自身定義的方法,而不僅僅是接口方法。
  • 性能較好: 在某些情況下,CGLIB 動態(tài)代理的性能可能比 JDK 動態(tài)代理更好。

缺點:

  • 需要第三方庫: 需要依賴 CGLIB 庫。
  • 實現(xiàn)復雜: CGLIB 動態(tài)代理的實現(xiàn)比較復雜,需要生成目標類的子類。
  • final 方法無法代理: 無法代理被 final 修飾的方法。
  • 對構造函數(shù)有要求: CGLIB 創(chuàng)建代理對象時,需要調用目標類的構造函數(shù)。 如果目標類沒有無參構造函數(shù),則需要手動指定構造函數(shù)。

示例代碼:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

// 目標類
class MyClass {
    public void doSomething() {
        System.out.println("MyClass is doing something...");
    }
}

// 方法攔截器
class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method: " + method.getName()); // 前置增強
        Object result = proxy.invokeSuper(obj, args); // 調用原始方法
        System.out.println("After method: " + method.getName()); // 后置增強
        return result;
    }
}

// 使用 CGLIB 動態(tài)代理
public class CGLIBDynamicProxyExample {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer(); // 創(chuàng)建 Enhancer 對象
        enhancer.setSuperclass(MyClass.class); // 設置超類
        enhancer.setCallback(new MyMethodInterceptor()); // 設置回調

        MyClass proxy = (MyClass) enhancer.create(); // 創(chuàng)建代理對象

        proxy.doSomething(); // 調用代理對象的方法,會被攔截
    }
}

3. Spring Boot 中的 AOP 配置

在 Spring Boot 項目中,可以通過以下方式配置 AOP:

添加 AOP 依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

編寫切面類:

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.demo.service.*.*(..))")
    public void beforeAdvice(JoinPoint joinPoint) {
        System.out.println("Before executing method: " + joinPoint.getSignature());
    }
}

配置代理方式:

  • 默認情況下,Spring AOP 會根據(jù)目標類是否實現(xiàn)了接口來選擇使用 JDK 動態(tài)代理或 CGLIB 動態(tài)代理。
  • 可以通過 @EnableAspectJAutoProxy 注解的 proxyTargetClass 屬性來強制使用 CGLIB 動態(tài)代理。
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true) // 強制使用 CGLIB 動態(tài)代理
public class AopConfig {
    // ...
}

總結:

特性JDK 動態(tài)代理CGLIB 動態(tài)代理
目標類要求必須實現(xiàn)接口不需要實現(xiàn)接口
代理對象生成方式實現(xiàn)接口繼承類
性能一般較好
易用性簡單復雜
是否需要第三方庫是 (net.sf.cglib)
適用場景目標類實現(xiàn)了接口,簡單 AOP 場景目標類沒有實現(xiàn)接口,需要代理類自身定義的方法,性能要求較高
@EnableAspectJAutoProxy默認值:falseproxyTargetClass = true

在實際開發(fā)中,Spring AOP 會自動選擇合適的代理方式。 如果沒有特殊需求,可以使用默認配置。

如果需要強制使用 CGLIB 動態(tài)代理,可以設置

@EnableAspectJAutoProxy(proxyTargetClass = true)

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • spring boot如何加入mail郵件支持

    spring boot如何加入mail郵件支持

    這篇文章主要介紹了spring boot如何加入mail郵件支持,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • java編程調用存儲過程中得到新增記錄id號的實現(xiàn)方法

    java編程調用存儲過程中得到新增記錄id號的實現(xiàn)方法

    這篇文章主要介紹了java編程調用存儲過程中得到新增記錄id號的實現(xiàn)方法,涉及Java數(shù)據(jù)庫操作中存儲過程的相關使用技巧,需要的朋友可以參考下
    2015-10-10
  • Jenkins Pipeline為Kubernetes應用部署增加狀態(tài)檢測腳本優(yōu)化

    Jenkins Pipeline為Kubernetes應用部署增加狀態(tài)檢測腳本優(yōu)化

    這篇文章主要為大家介紹了Jenkins Pipeline為Kubernetes應用部署增加狀態(tài)檢測腳本優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • SpringBoot獲取http數(shù)據(jù)、打印HTTP參數(shù)的4種方式

    SpringBoot獲取http數(shù)據(jù)、打印HTTP參數(shù)的4種方式

    Java的話本地打斷點可以調試獲取rest入?yún)?但是在生產環(huán)境可能我們獲取入?yún)ⅲ℉ttp?header/parameter)可能就沒有那么的輕松了,所以本文給大家介紹了SpringBoot獲取http數(shù)據(jù)、打印HTTP參數(shù)的4種方式,需要的朋友可以參考下
    2024-03-03
  • springboot如何通過不同的策略動態(tài)調用不同的實現(xiàn)類

    springboot如何通過不同的策略動態(tài)調用不同的實現(xiàn)類

    這篇文章主要介紹了springboot如何通過不同的策略動態(tài)調用不同的實現(xiàn)類,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • SpringCloud-Alibaba-Sentinel-配置持久化策略詳解

    SpringCloud-Alibaba-Sentinel-配置持久化策略詳解

    這篇文章主要介紹了SpringCloud-Alibaba-Sentinel-配置持久化策略,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • 新手學習java反射基礎

    新手學習java反射基礎

    Java反射就是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意方法和屬性;并且能改變它的屬性。下面我們來一起學習一下吧
    2019-06-06
  • 零基礎如何系統(tǒng)的學習Java

    零基礎如何系統(tǒng)的學習Java

    這篇文章主要介紹了零基礎如何系統(tǒng)的學習Java,很多朋友糾結這個問題,教材書不知道從何學起,今天小編給大家分享一篇教程幫助到家梳理這方面的知識
    2020-07-07
  • java實現(xiàn)肯德基收銀系統(tǒng)

    java實現(xiàn)肯德基收銀系統(tǒng)

    這篇文章主要為大家詳細介紹了java實現(xiàn)肯德基收銀系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • mybatis中#{}和${}的區(qū)別詳解

    mybatis中#{}和${}的區(qū)別詳解

    本文主要介紹了mybatis中#{}和${}的區(qū)別詳解,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評論