全称:Service Provider Interface 服务发现机制.它可以用于实现框架扩展或者组件替换.
本质
SPI的核心思想就是解耦。
将接口实现类的全限定名配置在文件中,并且由服务器读取配置文件,这样就可以加载写入的实现类,运行中就可以动态替换接口实现类.
位置
META-INF/services 下面定义配置文件,通过特殊的类加载器,启动的时候加载文件中定义的类.
这个位置在ServiceLoader加载器中定义了,因此位置无法改变
PREFIX+实现类全限定名,即可找到对应的实现类
文件名为实现类的接口的全限定名,内容为实现类的全限定名
使用ServiceLoader.load加载Animals这个接口的实现类迭代器(文件中配置的实现类都会加载在上面).
通过迭代器,可以获取所有类.
// 1.通过load获得类的列表
ServiceLoader<Animals> load = ServiceLoader.load(Animals.class);
// 2. 迭代器遍历
Iterator iterator = load.iterator();
while (iterator.hasNext()) {
Animals next = (Animals) iterator.next();
System.out.println(next.toString());
}
当配置文件中只有一个类时,那么最后也只会展示一个类的信息;
通过这个配置文件,我们可以通过改变配置文件来动态改变类的信息.
这个可以使用在策略模式中
策略模式SPI实现开闭原则
直接迭代实现类,并且进行判断获得对应的对象
public static Animals getAnimals(String type) {
ServiceLoader<Animals> load = ServiceLoader.load(Animals.class);
Iterator<Animals> iterator = load.iterator();
while(iterator.hasNext()) {
Animals animals = iterator.next();
if (type.equals(animals.typeName())) {
return animals;
}
}
return null;
}
执行
public static void main(String[] args) {
Animals 松鼠 = SPIAnimalsFactory.getAnimals("松鼠");
System.out.println("松鼠:"+松鼠);
Animals 熊猫 = SPIAnimalsFactory.getAnimals("熊猫");
System.out.println("熊猫:"+熊猫);
}
结果:
松鼠:Songshu{name='松鼠',foodType='松果',songguoNum=10} 熊猫:Panda{name='熊猫',foodType='竹子',zhuziName=20}