SPI全称Service Provider Interface, 是Java提供的一套用来被第三方实现或者扩展的接口
实际上是"基于接口的编程+策略模式+配置文件"组合实现的动态加载机制, 更是设计模式的生动体现
它可以用来启用框架扩展和替换组件. SPI的作用就是为这些被扩展的API寻找服务实现
我们一般推荐模块之间基于接口编程, 模块之间不对实现类进行硬编码, 一旦代码里涉及具体的实现类, 就违反了可拔插的原则, 如果需要替换一种实现, 就需要修改代码
public interface UploadFile {
void upload(String file);
}
public class AliyunCDN implements UploadFile {
@Override
public void upload(String url) {
System.out.println("upload to AliyunCDN");
}
}
public class QiniuCDN implements UploadFile {
@Override
public void upload(String url) {
System.out.println("upload to QiniuCDN");
}
}
然后需要在resources目录下新建META-INF/services目录, 并且在这个目录下新建一个与上述接口的全限定名一致的文件, 在这个文件中写入接口的实现类的全限定名
org.test.AliyunCDN
org.test.QiniuCDN
启动类
public class Test {
public static void main(String[] args) {
ServiceLoader<UploadFile> uploadFiles = ServiceLoader.load(UploadFile.class);
for (UploadFile u : uploadFiles) {
u.upload("filePath");
}
}
}
项目结构
C:
├─pom.xml
└─src
└─main
├─java
│ └─org
│ └─test
│ AliyunCDN.java
│ QiniuCDN.java
│ Test.java
│ UploadFile.java
└─resources
└─META-INF
└─services
org.test.UploadFile
运行
upload to AliyunCDN
upload to QiniuCDN
Spring中大量使用了SPI, 比如: 对Servlet3.0规范对ServletContainerInitializer的实现(Tomcat加载SpringBoot项目的War包)/自动类型转换Type Conversion SPI(Converter SPI/Formatter SPI)等
SpringBoot中spring.factories和SpringFactoriesLoader
拼音工具-PinyinUtil 官方文档
和其它门面模块类似,采用SPI方式识别所用的库。例如你想用Pinyin4j,只需引入jar,Hutool即可自动识别。
Dubbo中也大量使用SPI的方式实现框架的扩展, 不过它对Java提供的原生SPI做了封装,允许用户扩展实现Filter接口
JDBC4.0以后不再需要Class.forName即可注册驱动
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。