摘要

极客时间里的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。

动态代理的应用也有很多:
  • 可以使用 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