Follow me on GitHub

类加载(七):SPI 与线程上下文类加载器

双亲委派模型并不完美,有其固有缺陷,SPI 机制必须破坏双亲委派。

可见性

双亲委派会影响 被加载类 之间的可见性,若类加载器 A 的父类加载器为 B,则:

  • B 加载的类对 A 加载的类可见;
  • A 加载的类对 B 加载的类不可见;

因此应用本身的代码可以使用 JDK 核心类库,但反之不行,典型例子即 SPI 机制。

线程上下文类加载器

Java 通过线程上下文类加载器解决 SPI 中核心类库 反过来 调用用户代码的问题,它违反了双亲委派模型。

每个线程都关联一个类加载器,它的设置、访问为:

  • 访问:getContextClassLoader
  • 设置:
    • 继承父线程的上下文类加载器
    • Thread.setContextClassLoader 显式设置

若应用全局范围内都没有设置过该字段,则 所有线程 的上下文类加载器默认为 应用(系统)类加载器

所谓的线程上下文类加载器并非一个特殊的 ClassLoader 子类,它只是 Thread 类的一个字段而已,可以把 任何 ClassLoader 设置为线程的上线文类加载器。

借助上下文类加载器,可以打破双亲委派的依赖关系,原本被 系统类加载器 加载的 用户 SPI 实现 无法被 JDK 核心类库调用,此时 SPI 实现可以由 线程上下文类加载器 加载,进而可被核心类库调用。