什么是SPI 

一种服务加载方式,全名为Service Provider Interface,Service提供者接口

如果我们要抽象里面的模块,在面对对象编程当中,我们模块之间,一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。
一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。
为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。
有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。所以SPI的核心思想就是解耦

通俗例子解释:

例子:
JDK中有支持音乐播放,假设只支持mp3的播放,有些厂商想在这个基础之上支持mp4播放,有的想支持mp5播放,
而这些厂商都是第三方厂商,如果没有提供SPI这种实现标准,那就只有修改JAVA的源代码了。
有了SPI标准,JDK的爸爸SUN公司只需要提供一个播放接口,在实现播放的功能上通过ServiceLoad的方式加载服务,
那么第三方只需要实现这个播放接口,再按SPI标准的约定进行打包,再放到classpath下面就OK了

SPI的机制约定:

1)         在jar包的META-INF/services/目录中创建以接口全限定名命名的文件该文件内容为Api具体实现类的全限定名

2)         服务调用方用java.util.ServiceLoader,用服务接口为参数,去动态加载具体的实现类到JVM中

3)         如SPI的实现类为Jar则需要放在主程序classPath中

4)         定义服务的通用接口,针对通用的服务接口,提供具体的实现类

//通用接口,
public interface SendMessage {
void send(String msg);
}
package com.quan.spi.emailimp;

import com.quan.spi.api.SendMessage;

//通用接口的实现类1
public class SendMessageEmail implements SendMessage { @Override
public void send(String msg) {
System.out.println("send " + msg +" use email"); }
}
package com.quan.spi.phoneimp;

import com.quan.spi.api.SendMessage;

//通用接口的实现类2
public class SendMessagePhone implements SendMessage {
@Override
public void send(String msg) {
System.out.println("send " +msg +" use phone");
}
}
//通过工厂模式去获得sendmessage
public class SendMessageFactory {
public SendMessageFactory() {
} public static SendMessage getsend(){
SendMessage sendMessage = null;
ServiceLoader<SendMessage> sendMessages = ServiceLoader.load(SendMessage.class);
Iterator iterator = sendMessages.iterator();
while (iterator.hasNext()){
sendMessage = (SendMessage) iterator.next();
sendMessage.send("quan");
}
return sendMessage;
}
}

META-INF/services:

名字为:com.quan.spi.api.SendMessage

com.quan.spi.emailimp.SendMessageEmail
com.quan.spi.phoneimp.SendMessagePhone

测试:

package com.quan.spi;

import com.quan.spi.api.SendMessage;
import org.junit.Test; import java.util.ServiceLoader; public class TestMessage {
@Test
public void Test(){
SendMessageFactory.getsend();
} @Test
public void Test2(){
ServiceLoader<SendMessage> sendMessages = ServiceLoader.load(SendMessage.class);
for (SendMessage s : sendMessages) {
s.send("quanquan");
}
} }

SPI简单解析的更多相关文章

  1. 对 cloudwu 简单的 cstring 进行简单解析

    题外话 以前也用C写过字符串,主要应用的领域是,大字符串,文件读取方面.写的很粗暴,用的凑合着.那时候看见云风前辈的一个开源的 cstring 串. 当时简单观摩了一下,觉得挺好的.也没细看.过了较长 ...

  2. 基于DOM的XSS注入漏洞简单解析

    基于DOM的XSS注入漏洞简单解析http://automationqa.com/forum.php?mod=viewthread&tid=2956&fromuid=21

  3. 15.5 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表

    点击返回:自学Zabbix之路 自学Zabbix之路15.5 Zabbix数据库表结构简单解析-其他 表  1. Actions表 actions表记录了当触发器触发时,需要采用的动作. 2.Aler ...

  4. 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)

    深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...

  5. List<T>集合的Sort自定义排序用法简单解析

    List<T>集合的Sort自定义排序用法简单解析: 如下:一系列无序数字,如果想要他们倒序排列,则使用如下代码: 那么如何理解这段代码呢? (x,y)表示相邻的两个对象,如果满足条件:x ...

  6. Maven项目pom.xml文件简单解析

    Maven项目pom.xml简单解析 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="h ...

  7. 自学Zabbix之路15.1 Zabbix数据库表结构简单解析-Hosts表、Hosts_groups表、Interface表

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.1 Zabbix数据库表结构简单解析-Hosts表.Hosts_grou ...

  8. 自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.2 Zabbix数据库表结构简单解析-Items表 Items表记录了i ...

  9. 自学Zabbix之路15.3 Zabbix数据库表结构简单解析-Triggers表、Applications表、 Mapplings表

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix之路15.3 Zabbix数据库表结构简单解析-Triggers表.Applica ...

随机推荐

  1. 微信小程序实现文本的展开与收起

    致谢 https://www.jianshu.com/p/9458083214cc 效果图   代码 js部分 // pages/volunteer/active/info/activeInfo.js ...

  2. Python "爬虫"出发前的装备之二数据先行( Requests 模块)

    1. 概念 爬虫不是动物,而是一种计算机程序. 这种程序有自己特定的功能,能按照使用者给定的一系列规则自行浏览万维网并获取需要的信息.此类程序被称为 网络爬虫(web crawler) 或 网络蜘蛛( ...

  3. C# Debug和Trace:输出调试信息

    在 C# 语言中允许在程序运行时输出程序的调试信息,类似于使用 Console.WriteLine 的方式向控制台输出信息.所谓调试信息是程序员在程序运行时需要获取的程序运行的过程,以便程序员更好地解 ...

  4. 【C# 基础概念】表达式(expression)、语句(statement)、块(block),指令(using)

    官方链接:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/statements-expressions-operato ...

  5. 使用ODBC连接MySQL和EXCEL

    1.安装ODBC 安装MySQL的时候,可以直接把ODBC一并安装了.如果没有安装的话,则在 https://dev.mysql.com/downloads/connector/odbc/ 下载相应的 ...

  6. 深入理解ThreadLocal及其变种

    ThreadLocal 定义 ThreadLocal很容易让人望文生义,想当然地认为是一个"本地线程". 其实,ThreadLocal并不是一个Thread,而是Thread的局部 ...

  7. Qt:QTableWidgetItem

    0.说明 QTableWidgetItem指明QTableWidget中的一个Item.Item通常包含文本.图标.checkbox. 最常用的构造Item的方式是:不指定该Item所在的TableW ...

  8. 错误try……except……else……finally 记录错误logging 抛出错误raise

    1.错误处理机制 try--except--finally 格式: try: 可能出错的代码 except xxx1Error as e: 处理1 except xxx2Error as e: 处理2 ...

  9. 分子动力学模拟之SETTLE约束算法

    技术背景 在上一篇文章中,我们讨论了在分子动力学里面使用LINCS约束算法及其在具备自动微分能力的Jax框架下的代码实现.约束算法,在分子动力学模拟的过程中时常会使用到,用于固定一些既定的成键关系.例 ...

  10. Python获取当前时间或者当前时间戳【转】

    取得时间相关的信息的话,要用到python time模块,python time模块里面有很多非常好用的功能,你可以去官方文档了解下,要取的当前时间的话,要取得当前时间的时间戳,时间戳好像是1970年 ...