java Service Provider Interface 简单示例

转载 2017年07月17日 18:10:45

SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。 目前有不少框架用它来做服务的扩展发现, 简单来说,它就是一种动态替换发现的机制, 举个例子来说, 有个接口,想运行时动态的给它添加实现,你只需要添加一个实现,

而后,把新加的实现,描述给JDK知道就行啦(通过改一个文本文件即可) 公司内部,目前Dubbo框架就基于SPI机制提供扩展功能。

简单示例

通过一个简单例子来说明SPI是如何使用的。 首先通过一张图来看看,用SPI需要遵循哪些规范,因为spi毕竟是JDK的一种标准。  我们首先需要一个目录,META-INF\services 如下,最终的目录路径就像这样:

1
2
3
4
5
6
7
8
9
10
11
12
└── src
├── com
│   └── ivanzhang
│       └── spi
│           ├── HelloInterface.java
│           ├── impl
│           │   ├── ImageHello.java
│           │   └── TextHello.java
│           └── SPIMain.java
└── META-INF
    └── services
        └── com.ivanzhang.spi.HelloInterface

文件名字为 接口/抽象类: 全名 文件内容: 接口/抽象类 实现类

就像这样: com.ivanzhang.spi.impl.TextHello com.ivanzhang.spi.impl.ImageHello

接下来, 我们需要定义接口和实现类:

1
2
3
public interface HelloInterface {
  public void sayHello();
}

实现类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TextHello implements HelloInterface {

  @Override
  public void sayHello() {
      System.out.println("Text Hello.");
  }

}

public class ImageHello implements HelloInterface {
  @Override
  public void sayHello() {
      System.out.println("Image Hello");
  }
}

最后,来看看,如果使用SPI机制,客户端代码:

1
2
3
4
5
6
7
8
9
10
11
public class SPIMain {
    public static void main(String[] args) {

        ServiceLoader<HelloInterface> loaders = 
              ServiceLoader.load(HelloInterface.class);

        for (HelloInterface in : loaders) {
            in.sayHello();
        }
    }
}

最后的输出: Text Hello.Image Hello

一个服务(service)通常指的是已知的接口或者抽象类,服务提供方就是对这个接口或者抽象类的实现,然后按spi标准存放到资源路径META-INF/services目录下,文件的命名为该服务接口的全限定名。如有一个服务接口com.test.Service,其服务实现类为com.test.ChildService,那此时需要在META-INF/services中放置文件com.test.Service,其中的内容就为该实现类的全限定名com.test.ChildService,有多个服务实现,每一行写一个服务实现,#后面的内容为注释,并且该文件只能够是以UTF-8编码。

    这种实现方式,感觉和我们通常的开发方式差不多,都是定义一个接口,然后子类实现父类中定义的方法,为什么要搞这么一套标准以及单独搞一个配置文件?这种方式主要是针对不同的服务提供厂商,对不同场景的提供不同的解决方案制定的一套标准,举个简单的例子,如现在的JDK中有支持音乐播放,假设只支持mp3的播放,有些厂商想在这个基础之上支持mp4的播放,有的想支持mp5,而这些厂商都是第三方厂商,如果没有提供SPI这种实现标准,那就只有修改JAVA的源代码了,那这个弊端也是显而易见的,也就是不能够随着JDK的升级而升级现在的应用了,而有了SPI标准,SUN公司只需要提供一个播放接口,在实现播放的功能上通过ServiceLoad的方式加载服务,那么第三方只需要实现这个播放接口,再按SPI标准进行打包成jar,再放到classpath下面就OK了,没有一点代码的侵入性。

SPI的全名为Service Provider Interface.大多数开发人员可能不熟悉,因为这个是针对厂商或者插件的。在java.util.ServiceLoader的文档里有比较详细的介绍。简单的总结下java spi机制的思想。我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块、jdbc模块的方案等。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。 java spi就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要.
java spi的具体约定为:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader


Double-checked locking: Clever, but broken

DCL:聪明的,但是不工作的你知道同步的真实含义吗?概要       许多java程序员熟悉double-checked locking的方法,它允许你执行延迟初始化,从而削减了同步的花费。虽然很多...
  • Befresh
  • Befresh
  • 2002-09-12 15:40:00
  • 1352

Java SPI(Service Provider Interface)简介

SPI 简介SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。一个服务(Service)通常指的是已知的接口或者抽象类,服务提供方就是对这...
  • FX_SKY
  • FX_SKY
  • 2016-07-17 21:15:13
  • 2753

Java的Service Provider Interface(SPI)

SPI是Java 1.5新添加的一个内置标准,允许不同的开发者去实现某个特定的服务。 一个​Service就是一套著名的接口或抽象类,而Service Provider是这个Service的一个特定...
  • woxueliuyun
  • woxueliuyun
  • 2014-01-09 22:16:10
  • 3201

jdk service provider interface

SPI 简介 SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。 目前有不少框架用它来做服务的扩展发现, 简单来说,它就是一种动态替换发...
  • youlianying
  • youlianying
  • 2014-09-01 11:00:51
  • 1811

Dao 的 Interface 和 Service 的 Interface

之前写 Spring MVC 时,傻乎乎的。由于不懂 Spring 是怎么进行注入的。以为只能靠 @Autowired,依赖 Interface 注入。其实 @Autowired 主要是根据类型进行注...
  • ginkov
  • ginkov
  • 2017-03-27 16:52:19
  • 1013

JSR 196: Java Authentication Service Provider Interface for Containers

JSR 196规范——Java身份认证服务提供器(Authentication Service Provider,简称ASP)容器接口界面。规范中定义了一个标准的服务提供器接口界面,综合了容器与验证机...
  • teamlet
  • teamlet
  • 2007-02-13 13:48:00
  • 1839

Developing a Service Provider using Java API(Service Provider Interface)

这篇关于SPI的文章是在blogspot上面,被ZF给强奸了,大多数人访问不了,就贴在这里,比较好懂。 From ServiceLoader javadoc: A service is a we...
  • fenglibing
  • fenglibing
  • 2011-12-19 11:23:55
  • 5640

服务提供者框架(Service Provider FrameWork)——jdbc连接

服务提供者框架组建: Service Interface  具体的业务逻辑实现 的协议,各大业内厂商根据自己的业务逻辑实现。Service Provider Interface "负责创建其服务...
  • lemon89
  • lemon89
  • 2015-04-18 12:42:09
  • 951

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

SPI 平时写代码一般不会用到,但是到了做一些基础组件开发或者是中间件开发的时候,SPI 是一个必须要掌握的知识点......
  • wenniuwuren
  • wenniuwuren
  • 2017-02-14 16:22:02
  • 520

Dabbo基础,注意事个人认知

1、Provider(服务提供方)先在注册中心注册自己的提供的服务。 说明: (1)、第2点中,address=”10.108.1.206:2181“...
  • u012152037
  • u012152037
  • 2016-02-29 10:56:33
  • 933
收藏助手
不良信息举报
您举报文章:java Service Provider Interface 简单示例
举报原因:
原因补充:

(最多只允许输入30个字)