之前开阿里的HSF框架,里面用到了Java的SPI机制,今天闲暇的时候去了解了一下,通过写博客来记录一下

SPI的全名为Service Provider Interface,我对于该机制的理解是为接口寻找服务实现类。现在公司的系统都是进行了模块的划分,系统抽象为多个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块、jdbc模块的方案等。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。于是就有了SPI这种服务发现机制。

java spi的具体使用如下  :

当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。

基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。

jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

参考案例:

项目文件结构:

参考代码:

Developer.java

package cn.edu.knowledge.spi;

public interface Developer {

    public String getPrograme();

}
JavaDeveloper.java

package cn.edu.knowledge.spi;

public class JavaDeveloper implements Developer {

    @Override

    public String getPrograme() {

        return "Java";
}
}

META-INF\services文件下的cn.edu.knowledge.spi.Developer文件内容是服务类的全限命名:

cn.edu.knowledge.spi.JavaDeveloper

将文件导出为jar包,新建一个项目,在项目中导入该jar,下面的测试类的代码

Test.java

import java.util.ServiceLoader;
import cn.edu.knowledge.spi.Developer;
public class Test { public ServiceLoader<Developer> serviceloader = ServiceLoader.load(Developer.class); public static void main(String[] arg) { Test devClient = new Test(); Developer dev = devClient.getDeveloper(); System.out.println(dev.getPrograme()); }
private Developer getDeveloper() { Developer lastdev = null; for (Developer dev : serviceloader) { System.out.println("out." + dev.getPrograme()); lastdev = dev; }
if(lastdev==null)
System.out.println("why...");
return lastdev; } }

我们在开发中都有用到SPI机制,但是我们没有意识到比如:

1.common-logging

apache最早提供的日志的门面接口。只有接口,没有实现。具体方案由各提供商实现,发现日志提供商是通过扫描  META-INF/services/org.apache.commons.logging.LogFactory 配置文件,通过读取该文件的内容找到日志提工商实现类。只要我们的日志实现里包含了这个文件,并在文件里制定   LogFactory工厂接口的实现类即可。

2.jdbc

jdbc4.0以前,开发人员还需要基于Class.forName("xxx")的方式来装载驱动,jdbc4也基于spi的机制来发现驱动提供商了,可以通过META-INF/services/java.sql.Driver文件里指定实现类的方式来暴露驱动提供者。

学习到的知识:面向接口编程可以实现接口和实现的分离,这样做的最大好处就是能够在客户端未知的情况下修改实现代码。那么什么时候应该抽象出Java接口呢?一种是用在层和层之问的调用。层和层之间是最忌讳耦合度过高或是改变过于频繁。设计优秀的接口能够解决这个问题。另一种是用在那些不稳定的部分上。如果某些需求的变化性很大,那么定义接口也是一种解决之道。设计良好的接口就像是我们日常使用的万用插座一样,不论插头如何变化,都可以使用。

Java之SPI机制的更多相关文章

  1. java 的SPI机制

    今天看到spring mvc 使用Java Validation Api(JSR-303)进行校验,需要加载一个 其具体实现(比如Hibernate Validator), 本来没有什么问题,但是突然 ...

  2. Java的SPI机制与简单的示例

    一.SPI机制 这里先说下SPI的一个概念,SPI英文为Service Provider Interface单从字面可以理解为Service提供者接口,正如从SPI的名字去理解SPI就是Service ...

  3. Java的Spi机制心得

    Java spi : 是Java EE 给服务供应商提供的接口,供应商遵循接口契约提供自己的实现.. 简单来讲就是为某个接口寻找服务实现的机制. 在看JDBC源码当看到DriverManage.get ...

  4. 深入理解 Java 中 SPI 机制

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/vpy5DJ-hhn0iOyp747oL5A作者:姜柱 SPI(Service Provider ...

  5. JAVA中SPI机制

    之前研究dubbo的时候就很好奇,里面各种扩展机制,期间也看过很多关于SPI的机制,今日有缘再度看到有文章总结,故记录一下, 首先了解一下 JAVA中SPI简单的用法 可参考这篇文章,https:// ...

  6. Java的SPI机制

    目录 1. 什么是SPI 2. 为什么要使用SPI 3. 关于策略模式和SPI的几点区别 4. 使用介绍或者说约定 4.1 首先介绍几个名词 4.2 约定 5. 具体的demo实现 5.1 创建服务提 ...

  7. Java spi机制浅谈

    最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现和接入都采用了java的spi机制. 所以简单的总结下java spi机制的思想. 我们系统里抽象的各个模块,往往有很多不同的实现方案,比 ...

  8. 聊聊Java SPI机制

    一.Java SPI机制 SPI(Service Provider Interface)是JDK内置的服务发现机制,用在不同模块间通过接口调用服务,避免对具体服务服务接口具体实现类的耦合.比如JDBC ...

  9. 你应该了解的 Java SPI 机制

    前言 不知大家现在有没有去公司复工,我已经在家办公将近 3 周了,同时也在家呆了一个多月:还好工作并没有受到任何影响,我个人一直觉得远程工作和 IT 行业是非常契合的,这段时间的工作效率甚至比在办公室 ...

随机推荐

  1. test md

    [TOC] Glossary SUT SYSTEM UNDER TEST CUT CLASS UNDER TEST MUT METHOD UNDER TEST Tests without Use of ...

  2. API各函数作用简介

    API各函数作用简介 1.控件与消息函数 AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小 AnyPopup 判断屏幕上是否存在任何弹出式窗口 ArrangeI ...

  3. Noip2013心态调整

    决定成绩的,很多时候可能不是实力,而是心态,一年走来,承受着一次次失败,怀疑,背负着希望与压力,突然发现,只有拥有过,失去过,才可以真正去超越,我希望完成我的梦想,但是唯有放下梦想,才可以走向它. 心 ...

  4. class类的sizeof计算

    class no_virtual { public: void fun1() const{} int fun2() const { return a; } private: int a; } clas ...

  5. 动态调用python类和函数

    类 class test1(object): def __init__(self): print "i am test1" class test2(object): def __i ...

  6. HDU 4633 Who's Aunt Zhang (Polya定理+快速幂)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4633 典型的Polya定理: 思路:根据Burnside引理,等价类个数等于所有的置换群中的不动点的个 ...

  7. Java Native Interface Specification(JNI)

    Java Native Interface Specification(JNI) 使用场景: 需要的功能,标准的java不能提供 有了一个用其他的语言写好的工具包,希望用java去访问它 当需要高性能 ...

  8. web前端的发展态势

     以前 作为一个java程序员写的代码主要还是后台的代码,虽然开始的时候前后端都写,但是也是用别人造好的轮子来用,学学html,css,js,jquery,再找一个前端ui框架学学,上手之后我们就可以 ...

  9. Cookie管理

    1,判断来访者是否第一次 public class VistorTest extends HttpServlet { @Override protected void doGet(HttpServle ...

  10. cocos2d-x 截取屏幕可见区域

    在游戏中,我们经常需要分享到社交网络的功能.分享时,我们时常会需要用到截屏的功能.目前网上的文章虽然很多,但是都是截取的 设计分辨率(DesignResolutionSize)大小的屏幕,而这个并不是 ...