java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot JDK动态代理和CGLIB动态代理的使用

SpringBoot项目中JDK动态代理和CGLIB动态代理的使用详解

作者:冰糖心书房

JDK动态代理和CGLIB动态代理都是SpringBoot中实现AOP的重要技术,JDK动态代理通过反射生成代理类,适用于目标类实现了接口的场景,性能较好,易用性高,但必须实现接口且不能代理final方法,CGLIB动态代理通过生成子类实现代理

在 Spring Boot 项目中,JDK 动态代理和 CGLIB 动态代理都是实现 AOP (面向切面编程) 的重要技术。 它们的主要区别在于代理对象的生成方式和适用范围。

下面详细介绍它们的使用场景:

1. JDK 动态代理 (JDK Dynamic Proxy)

原理:

使用场景:

优点:

缺点:

示例代码:

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

// 实现类
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 动态代理
public class JDKDynamicProxyExample {
    public static void main(String[] args) {
        MyInterface target = new MyClass(); // 创建目标对象
        MyInvocationHandler handler = new MyInvocationHandler(target); // 创建调用处理器

        // 创建代理对象
        MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
                MyInterface.class.getClassLoader(),
                new Class[] {MyInterface.class},
                handler
        );

        proxy.doSomething(); // 调用代理对象的方法,会被拦截
    }
}

2. CGLIB 动态代理 (CGLIB Dynamic Proxy)

原理:

使用场景:

优点:

缺点:

示例代码:

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 动态代理
public class CGLIBDynamicProxyExample {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer(); // 创建 Enhancer 对象
        enhancer.setSuperclass(MyClass.class); // 设置超类
        enhancer.setCallback(new MyMethodInterceptor()); // 设置回调

        MyClass proxy = (MyClass) enhancer.create(); // 创建代理对象

        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());
    }
}

配置代理方式:

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true) // 强制使用 CGLIB 动态代理
public class AopConfig {
    // ...
}

总结:

特性JDK 动态代理CGLIB 动态代理
目标类要求必须实现接口不需要实现接口
代理对象生成方式实现接口继承类
性能一般较好
易用性简单复杂
是否需要第三方库是 (net.sf.cglib)
适用场景目标类实现了接口,简单 AOP 场景目标类没有实现接口,需要代理类自身定义的方法,性能要求较高
@EnableAspectJAutoProxy默认值:falseproxyTargetClass = true

在实际开发中,Spring AOP 会自动选择合适的代理方式。 如果没有特殊需求,可以使用默认配置。

如果需要强制使用 CGLIB 动态代理,可以设置

@EnableAspectJAutoProxy(proxyTargetClass = true)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文