动态代理,Java

9次阅读
没有评论

 

既然你在复习 Spring Cloud 和 Spring Boot,那 Java 动态代理 绝对是绕不开的灵魂考点。因为无论是 Spring AOP声明式事务 (@Transactional) 还是 OpenFeign,底层全靠它。

面试时,建议按照 “静态代理的痛点 -> 两种实现方式 -> 核心区别” 的逻辑来回答。


1. 为什么要用动态代理?(解决什么问题)

  • 静态代理的痛点: 每一个目标类都要手动写一个代理类,如果有一百个 Service 要加日志,你就得写一百个代理,代码冗余,扩展性极差

  • 动态代理的优势: 代理类是在程序运行期间根据反射动态生成的。你只需要写一个通用的代理逻辑,就能代理各种各样的类。


2. Java 动态代理的两大主流实现

A. JDK 动态代理(Java 原生)

  • 核心: 基于接口

  • 关键类: java.lang.reflect.ProxyInvocationHandler

  • 原理: 利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用 InvokeHandler 来处理。

  • 要求: 目标类必须实现至少一个接口

B. CGLIB 动态代理(第三方库)

  • 核心: 基于继承

  • 关键类: MethodInterceptorEnhancer

  • 原理: 通过 ASM 字节码操作框架,动态生成目标类的一个子类,并覆盖其中的方法。

  • 要求: 目标类不能是 final 的,目标方法也不能是 final 的(因为子类没法重写)。


3. 面试必问:JDK vs CGLIB 怎么选?

维度 JDK 动态代理 CGLIB 动态代理
实现原理 Java 反射机制 ASM 字节码技术(直接修改字节码)
目标类限制 必须实现接口 只要不是 final 类即可
性能 较旧版本性能低,但 Java 8+ 已经优化得极好 老版本性能高,但创建代理对象较慢
归属 JDK 原生自带 第三方库(Spring 已内置)

Spring AOP 的策略:

  • 如果目标对象实现了接口,默认采用 JDK 动态代理。

  • 如果没有实现接口,则采用 CGLIB。

  • 你也可以在配置中强制使用 CGLIB (proxy-target-class="true")。


4. 核心代码演示(找回肌肉记忆)

如果你面试时需要手写或者描述流程,记住这几行核心:

JDK 代理核心:

Java

// 1. 实现 InvocationHandler 接口
public class MyHandler implements InvocationHandler {
    private Object target; // 目标对象
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 前置增强 (比如开启事务)
        Object result = method.invoke(target, args); // 执行原方法
        // 后置增强 (比如提交事务)
        return result;
    }
}

// 2. 生成代理对象
Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                       target.getClass().getInterfaces(), 
                       handler);

5. 常见面试连环炮

  • Q:为什么 JDK 代理一定要有接口?

    • A: 因为生成的代理类默认已经继承了 Proxy 类(Java 是单继承),所以它只能通过实现接口的方式来扩展功能。

  • Q:动态代理和装饰器模式有什么区别?

    • A: 装饰器模式侧重于静态地给对象增强功能,通常要手动编写;动态代理侧重于批量、动态地拦截方法,对开发者更透明。

  • Q:Spring 事务失效跟动态代理有关系吗?

    • A: 有!如果在同一个类中 A 方法调用 B 方法(B 带有 @Transactional),事务会失效。因为这属于自调用,没有经过代理对象,拦截逻辑就没生效。

小建议:

既然你之前在做 PancakeBot 的自动化交易和高级架构,可以跟面试官提一句:在处理交易信号的埋点监控或者性能统计时,你会考虑用 AOP(即动态代理)来做非侵入式的开发,这样显得你对技术的应用非常有落地感。

正文完
 0
bdspAdmin
版权声明:本站原创文章,由 bdspAdmin 于2026-04-08发表,共计1608字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)