Compare commits

...

4 Commits

Author SHA1 Message Date
Guide c9746ff2df
Merge pull request #2379 from mangyimang/main
Update spi.md
2024-04-29 17:45:29 +08:00
Guide c1d2b32359
Merge pull request #2381 from haorenlin/main
Update io-model.md
2024-04-29 17:44:55 +08:00
yanjunlin 18d066aa21
Update io-model.md
#0000 单词补全 java-io-模型详解
2024-04-29 16:13:16 +08:00
mangyimang ec5e3e7923
Update spi.md
问题来源:https://github.com/Snailclimb/JavaGuide/issues/2378
对于以上问题所指出的SPI机制的设计和使用场景的修正阐述
2024-04-25 16:23:39 +08:00
2 changed files with 11 additions and 1 deletions

View File

@ -18,6 +18,12 @@ head:
为了实现在模块装配的时候不用在程序里面动态指明这就需要一种服务发现机制。Java SPI 就是提供了这样一个机制:**为某个接口寻找服务实现的机制。这有点类似 IoC 的思想,将装配的控制权移交到了程序之外。**
java 也经常会制定一些规范,除了提供默认实现之外,也支持第三方提供其自己对于某规范的实现,例如 JDBC Java 数据库连接)驱动管理、日志框架、图片处理服务等。以 JDBC 为例JDBC 4.0 及其之后的版本使用 SPI 机制来自动发现和加载数据库驱动。开发者只需要将 JDBC 驱动的 JAR 包放在类路径下,无需通过 Class.forName() 来显式加载驱动类。
但是以上机制存在一个特定于 java 的问题即双亲委派模型不能很好地处理那些由Java核心库直接加载但又必须由加载到JVM中的第三方类实现的情况。因为核心类加载器不会去加载那些位于应用程序类路径classpath上的类这就导致了一个问题如何允许核心 Java API 能够加载由应用程序类加载器加载的类或接口的实现?
java 设计了一种机制来解决该问题,这就是 SPI 。
## SPI 介绍
### 何谓 SPI?
@ -332,6 +338,10 @@ public void reload() {
}
```
其解决第三方类加载的机制其实就蕴含在 `ClassLoader cl = Thread.currentThread().getContextClassLoader();` 中,`cl` 就是**线程上下文类加载器**Thread Context ClassLoader。这是每个线程持有的类加载器JDK的设计允许应用程序或容器如Web应用服务器设置这个类加载器以便核心类库能够通过它来加载应用程序类。
线程上下文类加载器默认情况下是应用程序类加载器Application ClassLoader它负责加载classpath上的类。当核心库需要加载应用程序提供的类时它可以使用线程上下文类加载器来完成。这样即使是由引导类加载器加载的核心库代码也能够加载并使用由应用程序类加载器加载的类。
根据代码的调用顺序,在 `reload()` 方法中是通过一个内部类 `LazyIterator` 实现的。先继续往下面看。
`ServiceLoader` 实现了 `Iterable` 接口的方法后,具有了迭代的能力,在这个 `iterator` 方法被调用时,首先会在 `ServiceLoader``Provider` 缓存中进行查找,如果缓存中没有命中那么则在 `LazyIterator` 中进行查找。

View File

@ -18,7 +18,7 @@ I/O 一直是很多小伙伴难以理解的一个知识点,这篇文章我会
### 何为 I/O?
I/O**I**nput/**O**utpu 即**输入/输出** 。
I/O**I**nput/**O**utput 即**输入/输出** 。
**我们先从计算机结构的角度来解读一下 I/O。**