【大白话说Java面试题】【Java基础篇】第30题:JDK动态代理和CGLIB动态代理有什么区别
2026/5/4 15:54:01 网站建设 项目流程
第30题:JDK动态代理和CGLIB动态代理有什么区别

📚回答:

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

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

  • 实现步骤

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

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

importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;interfaceService{voidexecute();}classTargetServiceimplementsService{@Overridepublicvoidexecute(){System.out.println("目标对象执行业务逻辑");}}classDynamicProxyHandlerimplementsInvocationHandler{privateObjecttarget;publicDynamicProxyHandler(Objecttarget){this.target=target;}@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{System.out.println("代理对象:前置处理");Objectresult=method.invoke(target,args);System.out.println("代理对象:后置处理");returnresult;}}publicclassMain{publicstaticvoidmain(String[]args){Servicetarget=newTargetService();Serviceproxy=(Service)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),newDynamicProxyHandler(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动态代理的基本实现:

importorg.springframework.cglib.proxy.Enhancer;importorg.springframework.cglib.proxy.MethodInterceptor;importorg.springframework.cglib.proxy.MethodProxy;classTargetService{publicvoidexecute(){System.out.println("目标对象执行业务逻辑");}}classCglibProxyimplementsMethodInterceptor{@OverridepublicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxyproxy)throwsThrowable{System.out.println("代理对象:前置处理");Objectresult=proxy.invokeSuper(obj,args);System.out.println("代理对象:后置处理");returnresult;}}publicclassMain{publicstaticvoidmain(String[]args){Enhancerenhancer=newEnhancer();enhancer.setSuperclass(TargetService.class);enhancer.setCallback(newCglibProxy());TargetServiceproxy=(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基础篇

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询