SPI
SPI
SPI 全称为 Service Provider Interface,是一种服务发现机制。
API:给消费者调用。SPI:给服务者提供接口,用户可以自定义类实现接口。类似于留了个插件槽,用户可以自定义插件使用。
SPI:破坏了双亲委派机制。例如:利用spi加载jdbc的java.sql.Driver,保证各个sql厂家实现自己的类。SLFJ等,兼容各种日志。
Bootstrap Classloader(只拿些rt.jar下的Stirng,Math等类)加载器拿到了Application ClassLoader加载器应该加载的类,就打破了双亲委派模型。(原本先让父类进行加载,父类本来也没有,才能被子类加载,现在通过SPI,直接在Bootstrap Classloader加载到JVM)
(先让父加载器加载,然后字加载器加载。)
工作机制:创建流程
public interface Robot {
void sayHello();
}
接下来定义两个实现类,分别为 OptimusPrime 和 Bumblebee。
public class OptimusPrime implements Robot {
@Override
public void sayHello() {
System.out.println("Hello, I am Optimus Prime.");
}
}
public class Bumblebee implements Robot {
@Override
public void sayHello() {
System.out.println("Hello, I am Bumblebee.");
}
}
接下来 META-INF/services 文件夹下创建一个文件,名称为 Robot 的全限定名 org.apache.spi.Robot。文件内容为实现类的全限定的类名,如下:
org.apache.spi.OptimusPrime
org.apache.spi.Bumblebee
做好所需的准备工作,接下来编写代码进行测试。
public class JavaSPITest {
@Test
public void sayHello() throws Exception {
ServiceLoader<Robot> serviceLoader = ServiceLoader.load(Robot.class);//相当于获取到所有实现接口的类
System.out.println("Java SPI");
serviceLoader.forEach(Robot::sayHello);
}
}
最后来看一下测试结果,如下:
从测试结果可以看出,我们的两个实现类被成功的加载,并输出了相应的内容。关于 Java SPI 的演示先到这里,接下来演示 Dubbo SPI。
例子:jdbc的实现,mysql包下会配置一个文件,包含需要SPI加载的类。
DriverManager.getcollection(url,user,password);
可以看到DriverManager在初始化时会使用ServiceLoader来加载java.sql.Driver的实现类。(加载驱动不应该是Class.forName吗?)
确实JDBC驱动的加载是在Class.forName这一步完成的,但是后面的jdbc版本也支持SPI加载。(即使不写Class.forName也能加载成功)
(判断逻辑:如果Class.forName加载了数据库驱动,则不适用SPI加载,否则选择SPI进行加载。根据url的不同加载不同的驱动)
这个自动加载采用的技术叫做SPI,数据库驱动厂商也都做了更新。可以看一下jar包里面的META-INF/services目录,里面有一个java.sql.Driver的文件,文件里面包含了驱动的全路径名。
比如mysql-connector里面的内容:
com.mysql.jdbc.Driver
com.mysql.fabric.jdbc.FabricMySQLDriver
作者:tracy_668
链接:https://www.jianshu.com/p/f6653220a3e7
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
2.2 Dubbo SPI 示例(增强javaSPI)
Dubbo 并未使用 Java SPI,而是重新实现了一套功能更强的 SPI 机制。Dubbo SPI 的相关逻辑被封装在了 ExtensionLoader 类中,通过 ExtensionLoader,我们可以加载指定的实现类。Dubbo SPI 所需的配置文件需放置在 META-INF/dubbo 路径下,配置内容如下。
optimusPrime = org.apache.spi.OptimusPrime
bumblebee = org.apache.spi.Bumblebee
与 Java SPI 实现类配置不同,Dubbo SPI 是通过键值对的方式进行配置,这样我们可以按需加载指定的实现类。另外,在测试 Dubbo SPI 时,需要在 Robot 接口上标注 @SPI 注解。下面来演示 Dubbo SPI 的用法:
public class DubboSPITest {
@Test
public void sayHello() throws Exception {
ExtensionLoader<Robot> extensionLoader =
ExtensionLoader.getExtensionLoader(Robot.class);
Robot optimusPrime = extensionLoader.getExtension("optimusPrime");//可以获得明确的实现类
optimusPrime.sayHello();
Robot bumblebee = extensionLoader.getExtension("bumblebee");
bumblebee.sayHello();
}
}
微信公众号也会更新哦!!