SPI机制是什么?
SPI(Service Provider Interface)是JDK内置的服务发现机制,用在不同模块间通过接口调用服务,避免对具体服务服务接口具体实现类的耦合。比如JDBC的数据库驱动模块,不同数据库连接驱动接口相同但实现类不同,在使用SPI机制以前调用驱动代码需要直接在类里采用Class.forName(具体实现类全名)的方式调用,这样调用方依赖了具体的驱动实现,在替换驱动实现时要修改代码。而采用SPI机制后,在驱动jar包的META-INF/services下面新建一个驱动接口全名的UTF-8编码的文件,里面写上具体实现类的全名,这样调用方通过Java 的ServiceLoad接口动态的去加载接口的实现类,从而达到替换驱动实现不用修改代码的效果。
是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。本质上其实就是“基于接口编程+策略模式+配置文件”组合实现的动态加载机制。
使用步骤:
1、服务调用方通过ServiceLoader.load加载服务接口的实现类实例;
2、服务提供方实现服务接口后,在自己Jar包的META-INF/services目录下新建一个接口名全名的文件,并将具体实现类全名写入。
Spring SPI机制
其实很多开源框架库里都直接或间接使用了Java 的SPI机制。比如Spring就有类似的SPI机制,通过SpringFactoriesLoader代替JDK中ServiceLoader,通过META-INF/spring.factories文件代替META-INF/service目录下的描述文件,具体实现步骤不同,但原理都是使用Java 的反射机制。
什么时候用SPI
在面向对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可插拔的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候不用在程序里动态指明,这就需要一种服务发现机制。Java spi就是提供这样的一个机制:为某个接口寻找服务实现的机制。
很多开源框架中都采用了SPI思想,比如jdbc(Java 规定了JDBC的接口,可由不同厂商来实现MySQL,Oracle等),开源工具箱Geotools里面的DataStoreFactorySpi,我们可以自己去实现不同的DataStoreFactory,来支持不同数据引擎。
最后说白了,SPI就是一种将服务接口与服务实现分离以达到解耦、大大提升了程序可扩展行性的机制。引入服务提供者就是引入了SPI接口的实现者,通过本地注册来发现获取到具体的实现类。实现轻松可插拔。
如果想要应用案例的话我推荐可以看尚学堂Java300集,里面从初级到高级的项目练习都有讲到,适用范围也超广,大家可以从B站或者北京尚学堂官网直接搜索Java300集,高淇老师呕心力作,你值得拥有!