对Java中反射和动态代理的理解。
摘要
极客时间里的Java核心技术系列,第6讲,记录一些笔记。
关键词:introspect,proxy,asm,cglib,javassist,RPC,AOP
(主要说的是对 动态代理 的理解)
引入
- 一般来说,编程语言有静态和动态之分,数据有强类型和弱类型之分。
- 简单来说,语言类型信息在编译期检查的,就是静态语言;在运行期检查的,是动态语言。
- Java 是属于静态语言,强数据类型。
但是可以通过它的 反射机制 来实现部分动态语言的功能。
反射
Java中的反射可以让程序在运行中得到 类或对象的底层(直接操作他们),也就是程序在运行时的 自省(introspect) 的能力。
反射里有个 AccessibleObject.setAccessible(boolean flag) 的方法,可以在运行时修改成员的访问权限(private、protected、public这些)。
动态代理
首先明白代理的概念,代理就是对目标的一个包装,可以通过操作代理,进而操作目标。以此实现 调用者 和 是实现者 之间的解耦。
代理经历了静态代理和动态代理的发展:
-
静态代理:
实现写好代理类,所以这样每个业务类都需要写一个代理类,非常不灵活。用了 RMI 的古董技术,还需要rmic之类的工具静态生成 stub 等各种文件,
有很繁琐的准备工作,而这又与业务逻辑无关。RMI: Remote Method Invocation,远程方法调用。 (只用于Java)
可以让 一个Java虚拟机的对象 调用 另一个Java虚拟机的对象。
rmic: Java 自带的一个工具,在 bin 目录下。
-
动态代理:
在运行期间可以自动生成代理的对象。不需要我们自己准备 静态代理的那些繁琐的准备工作。
实现动态代理的方式有很多:
- 可以用JDK自身的动态代理,通过反射机制实现的。
需要实现对应的 InvocationHandler 接口, 重写 invoke 方法。
- 用字节码操作机制:
- ASM
是一个 Java 字节码的操控框架。可以动态生成类。
通过 树 这种数据类型,来表示 字节码的结构。 - cglib(基于ASM)
Code Generation Library
通过创建目标类的子类方式来实现。在子类中采用方法拦截的技术拦截父类方法的调用,顺势织入横切逻辑。
克服了对接口的依赖。 - Javassist
一个开源的分析、编辑和创建Java字节码的类库。
提供了 源码级和字节码级 2种级别的 API。
- ASM
动态代理的应用也有很多:
- 可以使用 RPC 包装。
RPC:Remote Procedure Call,远程过程调用。
一种进程间的通信方式,像调用本地服务一样调用远程服务。 - 完美的符合 AOP 切面编程的理念。
AOP: Aspect Oriented Programming,面向切面编程。
支持2种模式的动态代理: JDK Proxy、cglib。
个人认为对 AOP 解释比较 直观 的2张图:
参考链接:
https://juejin.im/post/5c1ca8df6fb9a049b347f55c
https://juejin.im/post/5a99048a6fb9a028d5668e62
https://www.ibm.com/developerworks/cn/java/j-lo-asm30/index.html
https://blog.csdn.net/a19881029/article/details/9465663
https://www.cnblogs.com/ygj0930/p/6542811.html