聊聊 Java SPI 机制(二)
此时就可以通过AnimalManagerLoader中的load方法去加载对应的实现类,封装到List集合中,调用如下:
public static void main(String[] args) {
AnimalManagerLoader animalManagerLoader = AnimalManagerLoader.getInstance();
List<AnimalSay> animalSays = animalManagerLoader.getAnimalSays();
for (AnimalSay animalSay : animalSays) {
animalSay.say();
}
}
那么此时提供声音的厂家就需要实现这个接口,比如狗狗的声纹厂家,实现如下:
/**
* 狗狗的声纹
*/
public class DogSay implements AnimalSay {
public void say() {
System.out.println("wang wang ~");
}
}
猫咪的声纹如下:
/**
* 猫咪的声纹
*/
public class CatSay implements AnimalSay {
@Override
public void say() {
System.out.println("miao miao ~");
}
}
实现类定义了,就需要在 /META-INF/services 中定义一个 com.myjszl.animal.api.AnimalSay文件,内容如下:
com.myjszl.dog.api.DogSay
com.myjszl.dog.api.CatSay
SPI 应用场景
SPI扩展机制应用场景有很多,比如Common-Logging,JDBC,Dubbo、ShardingSphere等等。
1. JDBC场景
java中定义的java.sql.Driver接口,并没有具体的实现,实现方式而是交给不同的服务厂商:
- 在MySQL的jar包mysql-connector-java-6.0.6.jar中,可以找到META-INF/services目录,该目录下会有一个名字为java.sql.Driver的文件,文件内容是com.mysql.cj.jdbc.Driver,这里面的内容就是针对Java中定义的接口的实现。
- PostgreSQL的jar包PostgreSQL-42.0.0.jar中,也可以找到同样的配置文件,文件内容是org.postgresql.Driver,这是PostgreSQL对Java的java.sql.Driver的实现。
2. ShardingSphere场景
在ShardingSphere中为了实现分布式事务提供了一个接口ShardingTransactionManager,但是在其架构中并未对其做出具体的实现,而是交给不同的厂商去实现,比如JTA强一致性事务的XAShardingTransactionManager,在其中META-INF/services就有一个org.apache.shardingsphere.transaction.spi.ShardingTransactionManager文件,如下图:
以上只是简单的列举了几个场景,实际应用场景很多,比如Spring、Spring Boot 中都有用到SPI设计。
3. Spring 场景
Spring中大量使用了SPI;比如:对servlet3.0规范对ServletContainerInitializer的实现、自动类型转换Type Conversion SPI(Converter SPI、Formatter SPI)等
4. SLF4J 日志门面 场景
SLF4J加载不同提供商的日志实现类,比如log4j、log4j2、logback.....
总结
通过Java的SPI机制能够很方便的实现可插拔、解耦的功能设计,在日常的开发中要能想到该机制并能灵活的运用。
文章转自公众号:码猿技术专栏