在Java中,我们经常会提到面向接口编程,这样减少了模块之间的耦合,更加灵活。
在一个项目中我们也通常将接口和实现类放在一起,但是如果哪天我们要替换其它的实现类,或者是修改实现类,涉及到实现类的代码也要相应地修改。
能不能这样:在调用服务的时候,我们只调用接口,不用关心实现类呢?无论我们怎么切换实现类,调用接口的部分代码都能正常运行?
当然是可以的,Java SPI (Service Provider Interface
)就提供了这样的机制。
Java SPI机制中,我们不再是手动指定接口和实现类的关系,而是让接口去寻找可用的实现类。
事实上,我们经常使用的Spring框架、日志接口等等,都是使用了SPI机制实现了扩展。
1,SPI
和API
在说起SPI
之前,我们还是先看一下API
,API
我们已经很熟悉了,和SPI
都可以被称作接口。
只不过API
的功能的实现,以及接口的定义全部是接口的实现者提供的,调用者只需要调用接口即可:
不过SPI
就不一样了,在SPI
机制中,调用者仍然是调用接口,但是这个接口是独立存在的,并且可以由不同的实现者实现:
也就是说,这里接口只是一个标准,并且提供接口的那一方并不一定回去实现接口,而是根据接口的定义,由更多的第三方实现。
这个接口可以由一个甚至是多个实现者去实现。也因此,调用者在调用接口时,可能还需要指定一下使用哪个实现者的实现类。
实现者也叫做服务提供者。
事实上,我们日常生活中经常使用的U盘也很类似SPI
机制,U盘使用的是USB接口,USB接口仅仅是一个规范(接口),但是发明USB接口的公司并没有去生产U盘,而是由不同的U盘厂商例如金士顿、闪迪(实现者)等等去根据这个规范生产U盘,然后我们就可以去选择自己喜欢的牌子(选择实现者)购买U盘,不过平时无论使用什么牌子的U盘,我们只需要插入到电脑的USB接口(调用接口&#x