Java|SPI(service provider interface 服务提供者接口)

零. 简介 SPI 是 JDK 1.5 后提供的一种服务扩展接口。目前有不少框架用它来做服务的扩展,如 Dubbo。
服务通常指接口(下述例子的 Hello 接口)或者抽象类,服务提供方(下述例子的CHello、JavaHello 类)就是对这个接口或者抽象类的实现,然后按spi标准存放到资源路径META-INF/services目录下,文件的命名(下述例子的com.wenniuwuren.spi.Hello)为该接口的全限定名,文件内容每一行写一个服务实现类,# 号后面为注释,该文件只能是 UTF-8 编码。再按 SPI 规范打包成 jar,再放到 classpath,没有一点代码的侵入性。 本质上和我们通常的开发方式一样,定义接口,子类实现父类,那很多人有疑问,为什么要开发这么一套规范? 这种方式主要是针对不同的服务提供方(插件开发、功能扩展等),对不同场景的提供不同的解决方案制定的一套标准,举个例子,如现在的 JDK 中支持数据库连接池,如果只支持某个连接池如 Druid,如果其他公司不想用这个 Druid 连接池,如果没有提供SPI 扩展,那就只有修改 Java 的源码,那就有个问题,要升级 JDK 就得再改一次代码,而有了 SPI 标准,JDK 只需要提供一个连接池接口,在实现连接池的功能上通过 ServiceLoad 的方式加载服务,那么第三方只需要实现这个连接池接口,就可以提供不同的服务。


一. 代码示例 Maven 项目结构:
Java|SPI(service provider interface 服务提供者接口)
文章图片




SPI 服务接口:


package com.wenniuwuren.spi; /** * Created by hzzhuyibin on 2017/2/14. */ public interface Hello {void sayHello(); }


SPI 服务提供方:
package com.wenniuwuren.spi.impl; import com.wenniuwuren.spi.Hello; /** * Created by hzzhuyibin on 2017/2/14. */ public class JavaHello implements Hello{ @Override public void sayHello() { System.out.println("Java Hello"); } }package com.wenniuwuren.spi.impl; import com.wenniuwuren.spi.Hello; /** * Created by hzzhuyibin on 2017/2/14. */ public class CHello implements Hello{ @Override public void sayHello() { System.out.println("C Hello"); } }



【Java|SPI(service provider interface 服务提供者接口)】配置文件 META-INF/services/com.wenniuwuren.spi.Hello:


com.wenniuwuren.spi.impl.CHello # C Hello com.wenniuwuren.spi.impl.JavaHello # Java Hello


pom.xml 打包示例配置:
Java|SPI(service provider interface 服务提供者接口)
文章图片





参考资料: http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html



    推荐阅读