最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现和接入都采用了java的spi机制。

所以简单的总结下java spi机制的思想。

我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块、jdbc模块的方案等。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。

为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。java spi就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。

java spi的具体约定如下 :

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

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

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

例子

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文件里指定实现类的方式来暴露驱动提供者。

3.自己编写简单例子

假设有一个内容搜索系统,分为展示和搜索两个模块。展示和搜索基于接口编程。搜索的实现可能是基于文件系统的搜索,也可能是基于数据库的搜索。实例代码如下

Search.java: 搜索接口

package search;  

import java.util.List;  

import definition.Doc;  

public interface Search {
    List<Doc> search(String keyword);
}  

FileSearch.java:文件系统的搜索实现

package search;  

import java.util.List;  

import definition.Doc;  

public class FileSearch implements Search {  

    @Override
    public List<Doc> search(String keyword) {
        System.out.println("now use file system search. keyword:" + keyword);
        return null;
    }  

}  

DatabaseSearch.java

package search;  

import java.util.List;  

import definition.Doc;  

public class DatabaseSearch implements Search {  

    @Override
    public List<Doc> search(String keyword) {
        System.out.println("now use database search. keyword:" + keyword);
        return null;
    }  

}  

SearchTest.java

package search;  

import java.util.Iterator;
import java.util.ServiceLoader;  

public class SearchTest {  

    public static void main(String[] args) {
        ServiceLoader<Search> s = ServiceLoader.load(Search.class);
        Iterator<Search> searchs = s.iterator();
        if (searchs.hasNext()) {
            Search curSearch = searchs.next();
            curSearch.search("test");
        }
    }
}  

最后创建在META-INF/services/search.Search文件。

当search.Search文件内容是"search.FileSearch"时,程序输出是:

now use file system search. keyword:test

当search.Search文件内容是"search.DatabaseSearch"时,程序输出是:

now use database search. keyword:test 

可以看出SearchTest里没有任何和具体实现有关的代码,而是基于spi的机制去查找服务的实现。

参考文献:

http://docs.oracle.com/javase/1.4.2/docs/guide/jar/jar.html#Service%20Provider

Java spi机制浅谈的更多相关文章

  1. java反射机制浅谈

    一.Java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...

  2. java的反射机制浅谈(转)

    原文链接:java的反射机制浅谈 一.java的反射机制浅谈 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...

  3. JDK源码解析之Java SPI机制

    1. spi 是什么 SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件. 系统设计的各个抽象,往往 ...

  4. 聊聊Java SPI机制

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

  5. Java SPI机制实战详解及源码分析

    背景介绍 提起SPI机制,可能很多人不太熟悉,它是由JDK直接提供的,全称为:Service Provider Interface.而在平时的使用过程中也很少遇到,但如果你阅读一些框架的源码时,会发现 ...

  6. 组件化框架设计之Java SPI机制(三)

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将从深入理解java SPI机制来介绍组件化框架设计: ...

  7. Java SPI 机制实现解耦与本地化

    SPI 是 Java 提供的一种服务加载方式,全名为 Service Provider Interface,可以避免在 Java 代码中写死服务的提供者,而是通过 SPI 服务加载机制进行服务的注册和 ...

  8. Java SPI机制详解

    Java SPI机制详解 1.什么是SPI? SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制.SPI是一种动态替换发现的机制, 比如有个 ...

  9. Java中的SPI原理浅谈

    在面向对象的程序设计中,模块之间交互采用接口编程,通常情况下调用方不需要知道被调用方的内部实现细节,因为一旦涉及到了具体实现,如果需要换一种实现就需要修改代码,这违反了程序设计的"开闭原则& ...

随机推荐

  1. 基于Mapxtreme for JAVA的电子地图设计与实现

    基于Mapxtreme for JAVA的电子地图设计与实现学生毕业设计,适合测绘类专业研究目标:        开发一个基于MapXtreme for JAVA的校园电子地图项目,使用MapInfo ...

  2. SpringBoot学习之自动依赖

    在前面使用SSM集成时,我们可以使用注解实现无配置化注入,但是这种依赖被进行“人工干预了的”,换句话就是说我们手动进行装配,那么此时还没有达到SpringBoot这种自动装配的效果,那么究竟Sprin ...

  3. C# 解决winform 窗体控件在窗体变化时闪烁的问题

    在窗体form代码中加入如下代码即可: protected override CreateParams CreateParams { get { CreateParams cp = base.Crea ...

  4. 使用webgl(three.js)搭建一个3D建筑,3D消防模拟——第三课

    项目背景 消防安全一直是各大都市关注的重要课题,在消防体系中,特别是高楼消防体系中,消防系统整体布控与监控,火情有效准确定位,防火器材定位,人员逃生路径规划,火情预警,消防演习都是特别重要的环节.所以 ...

  5. python (3.5)字符串 持续更新中………………

    # 字符串与变量连接输出 name = input("请输入姓名")age = input("请输入年龄")job = input("请输入工作&qu ...

  6. jquery post跨域请求数据

    原先一直以为要实现跨域请求只能用jsonp,只能支持GET请求,后来了解到使用POST请求也可以实现跨域,但是需要在服务器增加Access-Control-Allow-Origin和Access-Co ...

  7. jquery easyui panel title文字格式设置

    $('#txtLeftPercent').panel({ title: '剩余权重:' + '<b style="color:red">' + 100 + '%< ...

  8. java读取mysql表的注释及字段注释

    /** * 读取mysql某数据库下表的注释信息 * * @author xxx */ public class MySQLTableComment { public static Connectio ...

  9. Rails关闭html_safe字符串过滤

    在某些情况下我希望html的文本中包含一些换行,因为html5产生换行的方法是插入 <br />所以我可以这么写: text = "hello world!<br /> ...

  10. ubuntu16.04下安装opencv

    source url:http://blog.csdn.net/zhuiqiuk/article/details/5308505811 1 依赖包sudo apt-get install build- ...