对于Java中的Service类和SPI机制的透彻理解,也算是对Java类加载模型的掌握的不错的一个反映。
了解一个不太熟悉的类,那么从使用案例出发,读懂源代码以及代码内部执行逻辑是一个不错的学习方式。
一、使用案例
通常情况下,使用ServiceLoader来实现SPI机制。 SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。SPI是一种动态替换发现的机制, 比如有个接口,想运行时动态的给它添加实现,你只需要添加一个实现。
SPI机制可以归纳为如下的图:
起始这样说起来还是比较抽象,那么下面举一个具体的例子,案例为JDBC的调用例子:
案例如下:
JDBC中的接口即为:java.sql.Driver
SPI机制的实现核心类为:java.util.ServiceLoader
Provider则为:com.mysql.jdbc.Driver
外层调用则是我们进行增删改查JDBC操作所在的代码块,但是对于那些现在还没有学过JDBC的小伙伴来说(不难学~),这可能会有点难理理解,所以我这里就举一个使用案例:
按照上图的SPI执行逻辑,我们需要写一个接口、至少一个接口的实现类、以及外层调用的测试类。
但是要求以这样的目录书结构来定义项目文件,否则SPI机制无法实现(类加载机制相关,之后会讲):
E:.│ MyTest.java│├─com│ └─fisherman│ └─spi│ │ HelloInterface.java│ ││ └─impl│ HelloJava.java│ HelloWorld.java│└─META-INF └─services com.fisherman.spi.HelloInterface123456789101112131415
其中:
- MyTest.java为测试java文件,负责外层调用;
- HelloInterface.java为接口文件,等待其他类将其实现;
- HelloJava.java 以及 HelloWorld.java 为接口的实现类;
- META-INF
└─services
com.fisherman.spi.HelloInterface 为配置文件,负责类加载过程中的路径值。
首先给出接口的逻辑:
public interface HelloInterface { void sayHello();}123
其次,两个实现类的代码:
public class HelloJava implements HelloInterf