【大白话说Java面试题】【Java基础篇】第30题:JDK动态代理和CGLIB动态代理有什么区别
第30题JDK动态代理和CGLIB动态代理有什么区别回答核心对比JDK动态代理和CGLIB动态代理是两种常用的动态代理实现方式它们在底层原理、使用场景和限制条件上都有显著差异。以下是详细对比1. JDK动态代理定义JDK动态代理基于接口实现要求目标对象必须实现至少一个接口。实现步骤目标类需要实现一个接口。处理类实现InvocationHandler接口编写增强逻辑如日志记录、权限校验等。生成代理对象通过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.targettarget;}OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{System.out.println(代理对象前置处理);Objectresultmethod.invoke(target,args);System.out.println(代理对象后置处理);returnresult;}}publicclassMain{publicstaticvoidmain(String[]args){ServicetargetnewTargetService();Serviceproxy(Service)Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),newDynamicProxyHandler(target));proxy.execute();}}底层原理Proxy.newProxyInstance方法会根据传入的目标类加载器和接口信息动态生成一个代理类的字节数组。使用defineClass0本地方法将字节数组加载为代理类实例。代理类实现了目标接口代理对象调用接口方法时会触发InvocationHandler的invoke方法。使用场景AOP编程如Spring中的事务管理。MyBatis中Mapper接口的动态实现。2. CGLIB动态代理定义CGLIBCode Generation Library基于继承实现适用于没有实现接口的目标对象。实现步骤目标类无需实现接口但不能是final类或包含final方法。处理类实现MethodInterceptor接口编写增强逻辑。生成代理对象通过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(代理对象前置处理);Objectresultproxy.invokeSuper(obj,args);System.out.println(代理对象后置处理);returnresult;}}publicclassMain{publicstaticvoidmain(String[]args){EnhancerenhancernewEnhancer();enhancer.setSuperclass(TargetService.class);enhancer.setCallback(newCglibProxy());TargetServiceproxy(TargetService)enhancer.create();proxy.execute();}}底层原理CGLIB通过ASM技术动态生成目标类的子类并重写目标方法。当调用代理对象的方法时实际调用的是子类的重写方法该方法会触发MethodInterceptor的intercept方法。使用场景Spring框架中对未实现接口的Bean进行AOP代理。Hibernate框架中的延迟加载机制。3. 对比总结特性JDK动态代理CGLIB动态代理实现方式基于接口基于继承目标类要求必须实现接口无需实现接口但不能是final类性能性能略高性能稍低生成子类开销较大适用场景目标类实现接口的场景目标类未实现接口的场景面试官视角面试官可能会问“为什么Spring默认优先使用JDK动态代理”答因为JDK动态代理性能更高且大多数Spring Bean都会实现接口。面试官可能会追问“CGLIB有哪些局限性”答无法代理final类或final方法因为CGLIB通过继承实现而final修饰的类或方法无法被继承或重写。专栏大白话说Java面试题 — 01-Java基础篇