【大白话说Java面试题】【Java基础篇】第30题:JDK动态代理和CGLIB动态代理有什么区别

第30题:JDK动态代理和CGLIB动态代理有什么区别

📚 回答:

  • 核心对比
    JDK动态代理和CGLIB动态代理是两种常用的动态代理实现方式,它们在底层原理、使用场景和限制条件上都有显著差异。以下是详细对比:

1. JDK动态代理
  • 定义

    JDK动态代理基于接口实现,要求目标对象必须实现至少一个接口。

  • 实现步骤

    1. 目标类:需要实现一个接口。
    2. 处理类 :实现InvocationHandler接口,编写增强逻辑(如日志记录、权限校验等)。
    3. 生成代理对象 :通过Proxy.newProxyInstance方法动态生成代理对象。

    💡 代码示例

    以下代码展示了JDK动态代理的基本实现:

java 复制代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface Service {
    void execute();
}

class TargetService implements Service {
    @Override
    public void execute() {
        System.out.println("目标对象执行业务逻辑");
    }
}

class DynamicProxyHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理对象:前置处理");
        Object result = method.invoke(target, args);
        System.out.println("代理对象:后置处理");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Service target = new TargetService();
        Service proxy = (Service) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new DynamicProxyHandler(target)
        );
        proxy.execute();
    }
}
  • 底层原理

    • Proxy.newProxyInstance方法会根据传入的目标类加载器和接口信息,动态生成一个代理类的字节数组。
    • 使用defineClass0(本地方法)将字节数组加载为代理类实例。
    • 代理类实现了目标接口,代理对象调用接口方法时,会触发InvocationHandlerinvoke方法。
  • 使用场景

    • AOP编程(如Spring中的事务管理)。
    • MyBatis中Mapper接口的动态实现。

2. CGLIB动态代理
  • 定义

    CGLIB(Code Generation Library)基于继承实现,适用于没有实现接口的目标对象。

  • 实现步骤

    1. 目标类 :无需实现接口,但不能是final类或包含final方法。
    2. 处理类 :实现MethodInterceptor接口,编写增强逻辑。
    3. 生成代理对象 :通过Enhancer类动态生成代理对象。

    💡 代码示例

    以下代码展示了CGLIB动态代理的基本实现:

java 复制代码
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

class TargetService {
    public void execute() {
        System.out.println("目标对象执行业务逻辑");
    }
}

class CglibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("代理对象:前置处理");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("代理对象:后置处理");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(TargetService.class);
        enhancer.setCallback(new CglibProxy());

        TargetService proxy = (TargetService) enhancer.create();
        proxy.execute();
    }
}
  • 底层原理

    • CGLIB通过ASM技术动态生成目标类的子类,并重写目标方法。
    • 当调用代理对象的方法时,实际调用的是子类的重写方法,该方法会触发MethodInterceptorintercept方法。
  • 使用场景

    • Spring框架中对未实现接口的Bean进行AOP代理。
    • Hibernate框架中的延迟加载机制。

3. 对比总结
特性 JDK动态代理 CGLIB动态代理
实现方式 基于接口 基于继承
目标类要求 必须实现接口 无需实现接口,但不能是final
性能 性能略高 性能稍低(生成子类开销较大)
适用场景 目标类实现接口的场景 目标类未实现接口的场景

💡 面试官视角

  • 面试官可能会问"为什么Spring默认优先使用JDK动态代理?"
    答:因为JDK动态代理性能更高,且大多数Spring Bean都会实现接口。
  • 面试官可能会追问"CGLIB有哪些局限性?"
    答:无法代理final类或final方法,因为CGLIB通过继承实现,而final修饰的类或方法无法被继承或重写。

📌 专栏 :大白话说Java面试题 --- 01-Java基础篇

相关推荐
SQL-First布道者4 分钟前
持久层框架的评价标准:只有一个
java·spring boot·spring·tomcat·mybatis·spring jdbc
孔明click338 分钟前
Sa-Token v1.46.0 发布 🚀,来看看有没有令你心动的功能!
java·sa-token·开源·springboot·权限认证
ZJU_统一阿萨姆17 分钟前
【推理优化进阶】通信关键路径:NCCL、RDMA 与计算通信重叠
开发语言·人工智能·语言模型·架构·系统架构
黄敬峰20 分钟前
一文讲透 JWT 登录鉴权:token 的「颁发 → 存储 → 携带 → 校验」完整闭环
面试
m0_5873830032 分钟前
智慧场馆解决方案实战指南:从系统架构到落地部署全解析
java·spring boot·架构·系统架构
我不是疯子是傻子33 分钟前
Qt 程序打包部署全攻略:从 windeployqt 到 Inno Setup 的静默安装与版本迭代实战
开发语言·qt
ZC跨境爬虫36 分钟前
LeetCode 13. 罗马数字转整数(多解法详解 + Java Python 实现)
java·python·leetcode
省长42 分钟前
Sa-Token v1.46.0 发布 🚀,来看看有没有令你心动的功能!
java·后端·开源
tech_zjf1 小时前
当 AI 把 Next.js Route 越写越快:我为什么做了 next-route-kit
前端·后端
LayZhangStrive1 小时前
融360 一面
java·面试·后端开发