@@ -397,6 +397,56 @@ public class DebugInvocationHandler implements InvocationHandler {
397397
398398像 MyBatis、Hibernate 这种框架,能帮你把数据库查出来的一行行数据,自动变成一个个 Java 对象。它是怎么知道数据库字段对应哪个 Java 属性的?还是靠反射。它通过反射获取 Java 类的属性列表,然后把查询结果按名字或配置对应起来,再用反射调用 setter 或直接修改字段值。反过来,保存对象到数据库时,也是用反射读取属性值来拼 SQL。
399399
400+ ## 代理
401+
402+ 关于 Java 代理的详细介绍,可以看看笔者写的 [ Java 代理模式详解] ( https://javaguide.cn/java/basis/proxy.html " Java 代理模式详解 ") 这篇文章。
403+
404+ ### 如何实现动态代理?
405+
406+ 动态代理是一种非常强大的设计模式,它允许我们在** 不修改源代码** 的情况下,对一个类或对象的方法进行** 功能增强(Enhancement)** 。
407+
408+ 在 Java 中,实现动态代理最主流的方式有两种:** JDK 动态代理** 和 ** CGLIB 动态代理** 。
409+
410+ ** 第一种:JDK 动态代理**
411+
412+ Java 官方提供的,其核心要求是目标类必须实现一个或多个接口。JDK 动态代理在运行时,会利用 ` Proxy.newProxyInstance() ` 方法,动态地创建一个实现了这些接口的代理类的实例。这个代理类在内存中生成,你看不到它的 ` .java ` 或 ` .class ` 文件。
413+
414+ 当你调用代理对象的任何一个方法时,这个调用都会被转发到我们提供的一个 ` InvocationHandler ` 接口的 ` invoke ` 方法中。在 ` invoke ` 方法里,我们就可以在调用原始方法(目标方法)之前或之后,加入我们自己的增强逻辑。
415+
416+ ** 第二种:CGLIB 动态代理**
417+
418+ CGLIB 是一个第三方的代码生成库。它的原理与 JDK 完全不同,它不要求被代理的类实现接口。它在运行时,动态生成目标类的子类作为代理类(通过 ASM 字节码操作技术)。然后,它会重写父类(也就是被代理类)中所有非 ` final ` 、` private ` 和 ` static ` 的方法。
419+
420+ 当你调用代理对象的任何一个方法时,这个调用会被 CGLIB 的 ` MethodInterceptor ` 接口的 ` intercept ` 方法拦截。和 ` InvocationHandler ` 的 ` invoke ` 方法一样,我们可以在 ` intercept ` 方法里,在调用原始的父类方法之前或之后,加入我们的增强逻辑。
421+
422+ ### 静态代理和动态代理有什么区别?
423+
424+ 静态代理和动态代理的核心差异在于 ** 代理关系的确定时机、实现灵活性及维护成本** 。
425+
426+ | 对比维度 | 静态代理 (Static Proxy) | 动态代理 (Dynamic Proxy) |
427+ | ---------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
428+ | 代理关系确定时机 | 编译期(编译后生成固定的 ` .class ` 字节码文件) | 运行时(动态生成代理类字节码并加载到 JVM) |
429+ | 实现方式 | 手动编写代理类,需与目标类实现同一接口,一对一绑定 | 无需手动编写代理类,通过 ` Handler ` /` Interceptor ` 封装增强逻辑,一对多复用 |
430+ | 接口依赖 | 必须实现接口(代理类与目标类遵循同一接口规范) | 支持代理接口或直接代理实现类 |
431+ | 代码量与维护性 | 代码量大(目标类越多,代理类越多),维护成本高;接口新增方法时,目标类与代理类需同步修改 | 代码量极少(通用增强逻辑可复用),维护性好;与接口解耦,接口变更不影响代理逻辑 |
432+ | 核心优势 | 实现简单、逻辑直观,无额外框架依赖 | 灵活性强、复用性高,降低重复编码,适配复杂场景 |
433+ | 典型应用场景 | 简单的装饰器模式、少量固定类的增强需求 | Spring AOP、RPC 框架(如 Dubbo)、ORM 框架 |
434+
435+ ### ⭐️JDK 动态代理和 CGLIB 动态代理有什么区别?
436+
437+ 1 . JDK 动态代理是官方的,它要求被代理的类必须实现接口。它的原理是动态生成一个接口的实现类来作为代理。CGLIB 是第三方的,它不需要接口。它的原理是动态生成一个被代理类的子类来作为代理。但也正因为是继承,所以它不能代理 ` final ` 的类,被代理的方法也不能是 ` final ` 或 ` private ` 。
438+ 2 . 就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。
439+
440+ ### ⭐️介绍一下动态代理在框架中的实际应用场景
441+
442+ 动态代理最典型的应用场景就是** Spring AOP** 。
443+
444+ AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
445+
446+ Spring AOP 就是基于动态代理的,如果要代理的对象,实现了某个接口,那么 Spring AOP 会使用 ** JDK Proxy** ,去创建代理对象,而对于没有实现接口的对象,就无法使用 JDK Proxy 去进行代理了,这时候 Spring AOP 会使用 ** Cglib** 生成一个被代理对象的子类来作为代理,如下图所示:
447+
448+ ![ SpringAOPProcess] ( https://oss.javaguide.cn/github/javaguide/system-design/framework/spring/230ae587a322d6e4d09510161987d346.jpeg )
449+
400450## 注解
401451
402452### 何谓注解?
0 commit comments