Java基础之SPI机制
- 一、SPI机制的简单示例
- 1、案例分层
- 2、接口
- 3、实现类
- 4、测试类
- 5、结果
- 二、SPI机制的缺陷
一、SPI机制的简单示例
1、案例分层
resources 接下来可以在resources下新建META-INF/services/目录,然后新建接口全限定名的文件:com.example.demo.service.Search
,里面加上我们需要用到的实现类com.example.demo.service.impl.FileSearch
2、接口
public interface Search {
public List<String> searchDoc(String keyword);
}
3、实现类
public class FileSearch implements Search {
@Override
public List<String> searchDoc(String keyword) {
System.out.println("文件搜索 "+keyword);
return null;
}
}
4、测试类
@SpringBootTest
@Slf4j
public class SPITests {
@Test
void test1() {
ServiceLoader<Search> s = ServiceLoader.load(Search.class);
Iterator<Search> iterator = s.iterator();
while (iterator.hasNext()) {
Search search = iterator.next();
search.searchDoc("hello world");
}
}
}
5、结果
如果在com.example.demo.service.Search
文件里写上两个实现类,那最后的输出结果就是两行了。这就是因为ServiceLoader.load(Search.class)
在加载某接口时,会去META-INF/services
下找接口的全限定名文件,再根据里面的内容加载相应的实现类。这就是spi的思想,接口的实现由provider实现,provider只用在提交的jar包里的META-INF/services
下根据平台定义的接口新建文件,并添加进相应的实现类内容就好。
二、SPI机制的缺陷
- 不能按需加载,需要遍历所有的实现,并实例化,然后在循环中才能找到我们需要的实现。如果不想用某些实现类,或者某些类实例化很耗时,它也被载入并实例化了,这就造成了浪费。
- 获取某个实现类的方式不够灵活,只能通过 Iterator 形式获取,不能根据某个参数来获取对应的实现类。
- 多个并发多线程使用 ServiceLoader 类的实例是不安全的。
- 世界上那些最容易的事情中,拖延时间最不费力。
- 每个人都有属于自己的时刻表,别让任何人打乱你人生的节奏。
- 那是九月的秋天你写的信,传至十月我游荡在黄金稻穗间的魂儿手中,牵着它引入了十一月的深秋,告诉我,你在冬日暖炉旁等候。
- 成熟,是你出门总会自己带伞,很少再把自己淋湿;是你能控制自己的眼泪,很少再把自己感动哭。成熟是你学会善待自己,照顾好自己。你逐渐成为独立的个体,而不是将生活侥幸地寄托于外在的一切。没有人,一定会在雨夜去接你。没有人,一定会读懂你的心。
- 只要心情是晴朗的,人生就没有雨天。生活不必太刻意,只要自己默默的努力,生活总会给你惊喜。
- 圣诞老人是哪家快递的?活了十多年都没收到,差评。
- 百日宣言,鸣惊天下。
- 愿你如月光,明亮不清冷。
- 有志者自有千计万计,无志者只感千难万难。
- 年轻的态度与年轻的精神可以抹去心灵和面容上的皱纹,使眼睛充满光亮,使你看到未来。