interview
backend-classic
JDK 动态代理和 CGLIB 动态代理的区别是什么

后端经典面试题合集, JDK 动态代理和 CGLIB 动态代理的区别是什么?

后端经典面试题合集, JDK 动态代理和 CGLIB 动态代理的区别是什么?

QA

Step 1

Q:: JDK 动态代理和 CGLIB 动态代理的区别是什么?

A:: JDK 动态代理和 CGLIB 动态代理的主要区别在于它们的实现方式和适用场景。JDK 动态代理是基于接口的代理,它要求被代理的类必须实现一个或多个接口。JDK 动态代理在运行时生成代理类,主要通过 java.lang.reflect.Proxy 类来实现。CGLIB 动态代理则是基于类的代理,它通过生成目标类的子类来创建代理对象,不要求目标类必须实现接口。CGLIB 使用 ASM 字节码生成框架来在运行时生成代理类。由于是基于子类的方式,CGLIB 不能代理 final 方法。

Step 2

Q:: JDK 动态代理的实现原理是什么?

A:: JDK 动态代理的实现依赖于 Java 的反射机制。它通过 java.lang.reflect.Proxy 类来创建代理对象,并通过 InvocationHandler 接口来处理方法的调用。当调用代理对象的方法时,实际会调用 InvocationHandler.invoke() 方法,该方法接收被代理方法的信息,并可以在其中添加自定义逻辑(如日志记录、权限检查等),然后再决定是否调用原方法。

Step 3

Q:: CGLIB 动态代理的实现原理是什么?

A:: CGLIB 动态代理的实现原理是通过生成目标类的子类,并在子类中覆盖父类的方法。CGLIB 使用 ASM 字节码生成框架在运行时生成代理类的字节码,从而创建代理对象。代理类会拦截对目标方法的调用,并在调用前后执行额外的逻辑。由于 CGLIB 是通过子类代理的方式实现的,所以它不能代理 final 类和 final 方法。

Step 4

Q:: JDK 动态代理和 CGLIB 动态代理各自的优缺点是什么?

A:: JDK 动态代理的优点是实现简单,只要目标类实现了接口就可以进行代理,且生成的代理类较为轻量。缺点是只能代理实现了接口的类。CGLIB 动态代理的优点是可以代理没有实现接口的类,适用面更广。缺点是生成的代理类性能较低,且不能代理 final 类和 final 方法。此外,CGLIB 的实现更为复杂,生成的代理类占用的内存较多。

用途

面试这个内容是因为动态代理是 Java 开发中非常重要的一个概念,广泛应用于 AOP(面向切面编程)、Spring 框架中的事务管理、权限控制、日志记录等功能中。掌握 JDK 和 CGLIB 动态代理的区别与实现原理,可以帮助开发者在实际项目中选择合适的代理方式,提高代码的灵活性和可维护性。在实际生产环境中,动态代理经常用于需要对方法调用进行统一处理的场景,如对多个方法进行统一的权限检查、日志记录或事务控制。理解动态代理的工作机制有助于开发者在性能调优和问题排查时做出正确的判断。\n

相关问题

🦆
什么是 AOP?动态代理在 AOP 中的应用是什么?

AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,旨在将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来。动态代理是 AOP 实现的核心机制之一,特别是在 Spring 框架中,JDK 动态代理和 CGLIB 动态代理常用于实现 AOP 的切面逻辑,使得开发者可以在不修改业务代码的情况下,统一管理某些横切关注点。

🦆
什么是 ASM 框架?CGLIB 动态代理为什么依赖 ASM?

ASM 是一个 Java 字节码操纵框架,用于在运行时生成、修改和分析 Java 字节码。CGLIB 动态代理依赖 ASM 框架来生成目标类的子类的字节码。通过 ASM,CGLIB 可以在运行时生成符合 Java 规范的代理类,并在其中插入自定义逻辑,从而实现方法的拦截和增强。

🦆
JDK 动态代理的性能如何?在什么情况下可能会成为性能瓶颈?

JDK 动态代理的性能通常优于 CGLIB,因为它生成的代理类较为轻量。然而,由于 JDK 动态代理依赖于反射机制,反射调用的性能相对较低。如果代理的方法调用频繁且对性能要求较高,JDK 动态代理可能会成为瓶颈。在这种情况下,可以考虑直接使用 CGLIB 动态代理或者通过字节码生成技术来优化性能。

🦆
Spring 中如何选择使用 JDK 动态代理还是 CGLIB 动态代理?

在 Spring 中,如果目标类实现了接口,默认使用 JDK 动态代理。如果目标类没有实现接口,Spring 会自动切换为使用 CGLIB 动态代理。此外,开发者也可以通过配置强制指定使用 CGLIB 动态代理。在实际开发中,一般建议优先使用 JDK 动态代理,除非必须对没有实现接口的类进行代理。