版权声明:如需转载,请附上原文链接即可 https://blog.csdn.net/doujinlong1/article/details/82760426
Java中 SPI的使用
SPI(Service Provider Interface), 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。
1,SPI 的使用场景
SPI一般使用在一个接口有多个实现的情况,在外界无感的情况下可以实现自动的切换。比如在发短信的场景下,有多个供应商,可以使用SPI来做,保证服务的高可用。
如图:
实现一个动态加载的一个过程。
2,SPI 如何使用
2.1 有一个顶层接口
package com.test;
public interface MessageSender {
void send();
}
2.2 有一些底层实现
实现1:
package com.test;
public class ChinaMobileMessageSender implements MessageSender {
@Override
public void send() {
System.out.println("我是移动,我给你发短信");
}
}
实现2:
package com.test;
public class UnicomMessageSender implements MessageSender {
@Override
public void send() {
System.out.println("我是联通,我给你发短信");
}
}
2.3 写一个配置文件,特定目录下,特定名称,特定内容
在类路径(Spring架构下是src/main/resources 下即可)下创建/META-INF/services层次的文件夹,然后文件夹里创建以顶层接口全路径为名的文件,如图:
文件内容为每一个实现类的全路径为一行,如:
com.test.ChinaMobileMessageSender
com.test.UnicomMessageSender
3 测试一下 SPI
public static void main(String[] args) {
ServiceLoader<MessageSender> serviceLoader = ServiceLoader.load(MessageSender.class);
for (MessageSender messageSender : serviceLoader) {
messageSender.send();
}
}
console 输出:
扫描二维码关注公众号,回复:
3561528 查看本文章
我是移动,我给你发短信
我是联通,我给你发短信
4,总结
SPI 就是一个动态加载配置文件的策略模式实现,实现了解耦,可以自动加载到所有的子类,但是我也遇到一些问题。
1,在Spring的体系下,不知道是否可以做到加载到Spring容器中,从而使用其他的Spring加载的类。
2,不能动态选择使用的是哪一个子类,可能需要自己判断。
3,多线程下加载可能会有问题,所以还是需要初始化时加载好。
4,加载会一次性把所有子类都加载了,不能选择性加载。