Java中 SPI的使用

版权声明:如需转载,请附上原文链接即可 https://blog.csdn.net/doujinlong1/article/details/82760426

Java中 SPI的使用

SPI(Service Provider Interface), 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。

1,SPI 的使用场景

SPI一般使用在一个接口有多个实现的情况,在外界无感的情况下可以实现自动的切换。比如在发短信的场景下,有多个供应商,可以使用SPI来做,保证服务的高可用。

如图:

imagecaea84ba54f1b9bf.png

实现一个动态加载的一个过程。

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层次的文件夹,然后文件夹里创建以顶层接口全路径为名的文件,如图:

image475fdd46eca55b03.png

文件内容为每一个实现类的全路径为一行,如:

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,加载会一次性把所有子类都加载了,不能选择性加载。

猜你喜欢

转载自blog.csdn.net/doujinlong1/article/details/82760426