spi机制是什么鬼
引用自工匠小猪的技术世界之Java的spi机制
SPI(Service Provider Interface)是JDK内置的一种提供服务发现的机制。JDBC通过DriverManager.getConnection()来创建数据库连接就是应用了这种机制。
在java中根据一个子类获取其父类或接口信息非常方便,但是根据一个接口获取该接口所有实现类却没那么容易。有一种比较笨的办法就是扫描classpath下所有的class与jar包中的class,接着用ClassLoader加载进来,再判断是否是给定接口的子类。但是这种方法的代价太大,一般不会使用。
根据这个问题,java推出了ServiceLoader类来提供服务发现机制,动态的为某个接口寻找服务实现,这种机制有点类似IOC思想,将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。
当服务的提供者提供了服务接口的一种实现之后,必须根据SPI约定在 META-INF/services/
目录里创建一个以服务接口命名的文件,该文件里写的就是实现该服务接口的具体实现类。当程序调用ServiceLoader的load方法的时候,ServiceLoader能够通过约定的目录找到指定的文件,并装载实例化,完成服务的发现。
废话不说了上代码吧
接口类:
package com.qf58.task;
/**
* @Author: WangZhan
* @Description:
* @Date Created in 10:13 2018/7/11.
*/
public interface SPIService {
void spiTest(String message);
}
实现类:
package com.qf58.task;
/**
* @Author: WangZhan
* @Description:
* @Date Created in 10:17 2018/7/11.
*/
public class SPIServiceImpl implements SPIService {
@Override
public void spiTest(String message) {
System.out.println("收到的消息为:"+message);
}
}
配置文件:
下面是最关键的部分,就是如何创建META-INF并且打包的时候要将我们创建的文件打包进去,这里利用maven来实现:
<resources>
<resource>
<targetPath>${project.build.directory}/classes/META-INF/services</targetPath>
<directory>src/main/resources/META-INF/Services</directory>
<filtering>true</filtering>
<includes>
<include>com.qf58.task.SPIService</include>
</includes>
</resource>
</resources>
其中targetpath是打包完要生成的文件目录,directory是spi创建的文件存在的位置,include就是具体的文件。
应用
可以参考jdbc啦,暴露给用户一个接口,然后根据传的参数来实现某个功能。