title: SPI
tags: JDK,SPI,服务发现
grammar_cjkRuby: true
什么是SPI
SPI,JDK内置的一种服务提供发现机制,简单来说,就是一种动态替换机制。比如说,定义了一种规范,需要厂商去实现。对于应用方来说,只需将对应厂商的实现集成进来,就可以实现对该规范的实现,是一种插拔式的拓展手段。
为什么需要SPI
在面向对象的设计中,一般基于接口编程,模块之间不会对实现类进行硬编码,一旦涉及某一个实现类,需要动态指定或者修改该实现类,就要修改代码,就违反了可插拔的原则。而SPI的出现,弥补了这种问题。具体实现在模块之间无需动态指定,只需传进对应接口类型,就可以动态找到对应的实现类
如何实现SPI
SPI实现需要遵循以下规范:
- 需要在classpath路径创建一个文件夹,名为META-INF/services
- 需要在META-INF/services创建一个文件:
- 文件名为该接口的全路径名称
- 文件内容为该接口实现类的全路径
- 文件编码必须是UTF-8
- 通过java.util.ServiceLoader加载机制来获取
SPI实践
定义接口
public interface DataBaseDriver {
String connect(String host);
}
实现接口
package com.lung.spi.mysql;
import com.lung.spi.api.DataBaseDriver;
/**
* @Author: liumenglong
* @Date: 2018/9/3 10:31
* @Description:
*/
public class MysqlDriver implements DataBaseDriver {
public String connect(String s) {
return "Mysql Driver : "+s;
}
}
配置文件
1539239079579.png 1539239101366.png发现服务
1539239162411.pngSPI的优点和缺点
优点:
使用Java SPI机制的优势是实现解耦,使得第三方服务模块的装配控制的逻辑与调用者的业务代码分离,而不是耦合在一起。应用程序可以根据实际业务情况启用框架扩展或替换框架组件。
缺点:
虽然ServiceLoader也算是使用的延迟加载,但是基本只能通过遍历全部获取,也就是接口的实现类全部加载并实例化一遍。如果你并不想用某些实现类,它也被加载并实例化了,这就造成了浪费。获取某个实现类的方式不够灵活,只能通过Iterator形式获取,不能根据某个参数来获取对应的实现类。
多个并发多线程使用ServiceLoader类的实例是不安全的。
网友评论