文档章节

Java SPI_Service Provider Interface

秋风醉了
 秋风醉了
发布于 2015/12/29 18:39
字数 780
阅读 141
收藏 16
点赞 0
评论 0

Java SPI_Service Provider Interface

最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现和接入都采用了java的spi机制。所以简单的总结下java spi机制的思想。

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

 

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

 

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

基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

 

示例如下,使用Java SPI机制实现Compatator接口的服务实现。

package com.usoft;

/**
 * Created by xinxingegeya on 15/12/29.
 */
public class MyItem {

    private String name;
    private int level;

    public MyItem(String name, int level) {
        this.name = name;
        this.level = level;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    @Override
    public String toString() {
        return "MyItem{" + "level=" + level + ", name='" + name + '\'' + '}';
    }
}

Comparator实现一:

package com.usoft;

import java.util.Comparator;

/**
 * Created by xinxingegeya on 15/12/29.
 */
public class ComparatorProviderByLevel implements Comparator<MyItem> {
    @Override
    public int compare(MyItem o1, MyItem o2) {
        return o1.getLevel() - o2.getLevel();
    }
}

Comparator实现二:

package com.usoft;

import java.util.Comparator;

/**
 * Created by xinxingegeya on 15/12/29.
 */
public class ComparatorProviderByName implements Comparator<MyItem> {
    @Override
    public int compare(MyItem o1, MyItem o2) {
        return o1.getName().compareTo(o2.getName());
    }
}

classpath路径下的META-INF/services路径下建立以接口为名的文件,

java.util.Comparator

#为注释

#com.usoft.ComparatorProviderByName
com.usoft.ComparatorProviderByLevel

Main方法,

package com.usoft;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ServiceLoader;

/**
 * Created by xinxingegeya on 15/12/29.
 */
public class Main {

    private static ServiceLoader<Comparator> serviceLoader = ServiceLoader
        .load(Comparator.class, Thread.currentThread().getContextClassLoader());

    public static void main(String args[]) {
        List<MyItem> myList = new ArrayList<>();
        myList.add(new MyItem("c", 2));
        myList.add(new MyItem("a", 7));
        myList.add(new MyItem("d", 4));
        myList.add(new MyItem("b", 5));
//        Collections.sort(myList, new Comparator<MyItem>() {
//            @Override
//            public int compare(MyItem o1, MyItem o2) {
//                return o1.getLevel() - o2.getLevel();
//            }
//        });

        Collections.sort(myList, getComparator());
        showMyList(myList);

    }

    private static void showMyList(List<MyItem> list) {
        list.forEach(System.out::println);
    }

    private static Comparator<MyItem> getComparator() {
        for (Comparator<MyItem> comparator : serviceLoader) {
            System.out.println(comparator.getClass().getName());
            return comparator;
        }
        throw new RuntimeException("comparator is not found");
    }
}

参考文献:

http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html

=========END=========

本文转载自:http://singleant.iteye.com/blog/1497259

共有 人打赏支持
秋风醉了
粉丝 228
博文 577
码字总数 407134
作品 0
朝阳
程序员
Dubbo的SPI实现以及与JDK实现的区别

在 Java 里, 为了规范开发,制定了大量的「规范」与「标准」,这些上层的内容,大多是以接口的形式提供出来。那这些接口最终实现是谁呢,在哪里呢? 规范并不关心这个。 所谓规范,是指定了...

小红牛
06/28
0
0
我是SPI,我让框架更加优雅了!

文章首发于【陈树义的博客】,点击跳转到原文《我是 SPI,我让框架更加优雅了!》 自从上次小黑进入公司的架构组之后,小黑就承担起整个公司底层框架的开发工作。就在刚刚,小黑又接到一个任...

陈树义
07/16
0
0
聊聊Dubbo - Dubbo可扩展机制实战

摘要: 在Dubbo的官网上,Dubbo描述自己是一个高性能的RPC框架。今天我想聊聊Dubbo的另一个很棒的特性, 就是它的可扩展性。 1. Dubbo的扩展机制 在Dubbo的官网上,Dubbo描述自己是一个高性能...

阿里云云栖社区
06/04
0
0
聊聊Dubbo - Dubbo可扩展机制实战

1. Dubbo的扩展机制 在Dubbo的官网上,Dubbo描述自己是一个高性能的RPC框架。今天我想聊聊Dubbo的另一个很棒的特性, 就是它的可扩展性。 如同罗马不是一天建成的,任何系统都一定是从小系统不...

中间件小哥
05/29
0
0
JDBC中获取连接的两种途径:DRIVERMANAGER和DATASOURCE

java.sql.DriverManager The basic service for managing a set of JDBC drivers. NOTE: The interface, new in the JDBC 2.0 API, provides another way to connect to a data source. The ......

刘小兵2014
2011/07/29
0
0
Java控制树莓派GPIO口-Pi4J

Pi4J(http://pi4j.com/)是专门用来控制树莓派GPIO口以及通信的Java库。它有如下功能: Export & unexport GPIO pins Configure GPIO pin direction Configure GPIO pin edge detection Con......

李鱼跃龙门
2014/05/24
0
0
JDK源码之ClassLoader

Java类加载器ClassLoader总结 JAVA类装载方式,有两种: 1.隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中。 2.显式装载, 通过class.for...

村长大神
2014/03/27
0
0
Java SPI - ServiceLoader 使用简介

问题引入 以前一直想指定一套标准,让别人按照这个标准来实现,并编写好对应的容器。 然后我在代码中动态获取这些实现,让代码运行起来。 类似于写个 windows 环境,让开发者自己开发对应的软...

叶止水
05/27
0
0
dubbo client server demo

个客户端。 服务端 服务端maven父工程 首先搭建一个maven父工程,引入dubbo和spring的依赖,dubbo可以和spring无缝集成。 [html] view plaincopy <properties> <project.build.sourceEncodi...

cc-s
2015/10/29
0
0
SpringCloud(第 044 篇)链接Mysql数据库简单的集成Mybatis框架采用MapperXml访问数据库

SpringCloud(第 044 篇)链接Mysql数据库简单的集成Mybatis框架采用MapperXml访问数据库 - 一、大致介绍 二、实现步骤 2.1 添加 maven 引用包 2.2 添加应用配置文件(springms-provider-use...

HMILYYLIMH
2017/10/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Xamarin Essentials教程地理定位Geolocation

Xamarin Essentials教程地理定位Geolocation 通过地理定位功能,应用程序可以获取用户的当前地理位置,如经纬度值。利用地理位置,可以在地图上定位,也可以转化物理位置,划分用户的归属地。...

大学霸
13分钟前
0
0
vue 编译警告 Compiled with 4 warnings

There are multiple modules with names that only differ in casing. This can lead to unexpected behavior when compiling on a filesystem with other case-semantic. Use equal casing.......

落雪飞声
17分钟前
0
0
开篇文章,长期记录安全情形

密码位置 密码位于注释中 密码位于服务器端文件中 通过访问根目录下.htaccess、robots.txt查看禁查路径 密码文件可能存在的路径:/、/extra/、/extras/ 密码加密 binary to base16 sha256 彩虹...

hirainn
30分钟前
0
0
mysql数据库设置root可以远程登录的方法

mysql数据库设置root可以远程登录的方法 Posted on 2018-02-21 21:08 sishuisufeng 阅读(161) 评论(0) 编辑 收藏 允许root用户在任何地方进行远程登录,并具有所有库任何操作权限,具体操作如...

rootliu
35分钟前
0
0
TensorFlow 图的基本操作

图的创建,一般只需要使用默认图就能满足大部分的需求了 # 1 创建图的方法# 在默认图中创建常量c = tf.constant(0.0)# 新建一个图g = tf.Graph()# 设置上下文管理器,标明操作...

阿豪boy
今天
0
0
git 忽略文件失效

git update-index --assume-unchanged */.project

林子大鸟
今天
1
0
实现验证码功能

1、实现验证码,并存储 import com.dtb.pc_enterprise.entity.EnterUserEntity;import com.dtb.pc_enterprise.service.AdminService;import com.dtb.pc_enterprise.util.RedisService;......

木九天
今天
0
0
iptables 实例

以下部分内容为网络查询并整理结果 filter表小案例 iptables规则五条链:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING 四个表:filter nat mangle raw ###netfilter和iptables说明: 1、 ne...

李超小牛子
今天
0
0
Java面试基础篇——第六篇:常见Map类的区别

常见的map类有: HashMap, ConcurrentHashMap (Jdk1.8) , LinkedHashMap, TreeMap, Hashtable。 其中我们最常用的莫过于HashMap, 和并发情况下使用的ConcurrentHashMap了,它们的主要区别就在...

developlee的潇洒人生
今天
2
0
spring-boot:run启动时,指定spring.profiles.active

Maven启动指定Profile通过-P,如mvn spring-boot:run -Ptest,但这是Maven的Profile。 如果要指定spring-boot的spring.profiles.active,则必须使用mvn spring-boot:run -Drun.profiles=test......

夜黑人模糊灬
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部