SPI介绍
Java SPI (Service Provider Interface) 是 Java 中一种用于服务发现和服务加载的机制。SPI 允许第三方公司为 Java 平台提供服务,而无需修改 Java 代码。
SPI 的工作原理非常简单:
- 定义一个接口,该接口定义了服务的方法。
- 将接口的实现类放到一个特定的目录中,该目录由 Java 虚拟机(JVM)在运行时搜索。
- 使用 ServiceLoader 类加载服务提供者。
SPI对比Spring DI(Dependency Injection)
- 相同点:
都可以实例化类
- 不同点:
Spring DI通过扫描@Service,@Repository等注解
SPI通过加载/resources/META-INF/services配置文件
SPI demo
新建service接口
package com.mamba.springcloud.javabase.spi;
public interface AnimalService {
String type();
}
新建service实现类
package com.mamba.springcloud.javabase.spi;
public class CatService implements AnimalService{
@Override
public String type() {
return "Cat";
}
}
public class DogService implements AnimalService{
@Override
public String type() {
return "Dog";
}
}
/resources/META-INF/services下创建配置文件
文件名:接口全路径
com.mamba.springcloud.javabase.spi.AnimalService
文件内容:实现类全路径
com.mamba.springcloud.javabase.spi.CatService
com.mamba.springcloud.javabase.spi.DogService
工厂模式实例化service
静态代码块内,使用java.util.ServiceLoader加载service实现类
package com.mamba.springcloud.javabase.spi;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.ServiceLoader;
public class AnimalServiceFactory {
public static volatile Map<String, AnimalService> instances = new HashMap();
static {
ServiceLoader<AnimalService> services = ServiceLoader.load(AnimalService.class);
Iterator var5 = services.iterator();
while(var5.hasNext()) {
AnimalService item = (AnimalService)var5.next();
instances.put(item.type(), item);
}
}
}
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class AnimalServiceFactoryTest {
@Test
public void test() {
Map<String, AnimalService> instances = AnimalServiceFactory.instances;
instances.entrySet().forEach(entry -> {
System.out.println(entry.getKey() + " : " + entry.getValue().getClass().toString());
});
}
}