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


相关文章推荐

Java中的SPI(Service Provider Interface)介绍及示例

一个服务(service)通常指的是已知的接口或者抽象类,服务提供方就是对这个接口或者抽象类的实现,然后按spi标准存放到资源路径META-INF/services目录下,文件的命名为该服务接口的全限...
  • WQ560
  • WQ560
  • 2012年12月13日 12:30
  • 416

Java SPI(Service Provider Interface)简介

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

Java中的SPI(Service Provider Interface)

SPI(Service Provider Interface),一个Java内置的标准,允许不同的开发者去实现某个特定的服务。 A service is a well-known set of ...

Java的SPI(Service Provider Interface)规范

Java的SPI(Service Provider Interface)规范:规范内容当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以...

【Java实战】源码解析Java SPI(Service Provider Interface )机制原理

一、背景知识http://www.oracle.com/technetwork/articles/javase/extensible-137159.html

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

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

基于Windows Azure 包、Service Provider Foundation 和 Virtual Machine Manager的示例门户代码

原文地址:http://blogs.technet.com/b/privatecloud/archive/2013/11/28/sample-portal-code-based-on-windows-...

Creating your first Web Service provider and consumer in LotusScript and Java.

Creating your first Web Service provider and consumer in LotusScript and Java. Added by Simon O'D...

用Delphi实现Web Service的简单示例

  • 2014年11月10日 21:33
  • 756KB
  • 下载

Java简单的回调(interface)demo

  • 2017年01月04日 19:56
  • 2KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java Service Provider Interface 简单示例
举报原因:
原因补充:

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