Java SPI详细的例子
先翻一个来自于Baeldung的介绍:
为了更通俗易懂我就没有直译,如果有不严谨的地方请大神指教。
JavaSPI的定义
Java SPI defines four main components
SPI四个主要概念
1. Service
服务
A well-known set of programming interfaces and classes that provide access to some specific application functionality or feature.
服务是一组接口类,用来定义某些功能或特性的接口(常常是某个jar包的功能或特性),暴露给其他程序调用。
2. Service Provider Interface
服务提供者接口
An interface or abstract class that acts as a proxy or an endpoint to the service.
If the service is one interface, then it is the same as a service provider interface.
Service and SPI together are well-known in the Java Ecosystem as API.
一个接口或抽象类,用来代理一个服务端。
如果是一个接口服务,那么这就和一个服务提供者接口一样。
服务和SPI一起便是java生态中的API了。
还是来一段自己的理解吧。。。就是定义接口,用来被别人去实现
服务提供者接口 - 如果我们有一个MyService的接口,我们把接口打进jar包,留给别人去依赖并实现。那这个接口就是服务提供者的接口。我们简单的理解成这个jar是服务接口提供者。
没错,我们就是服务提供者。我们制定规则,定义接口。接下来留个各个厂商去实现各个接口。
比如JDBC,Java开发者把链接数据库的方法写成接口。这个接口只要传进去url name passwrod 就能链接DB了。这就是一个SPI
当然很重要一步的是要由每种不同的DB厂商去实现具体怎么用这么几个简单的参数去实现链接。厂商把实现打个jar包(比如:Oracle的ojdbc-xx.jar),开发者把他加到classpath中就可以链接数据库了。
3. Service Provider
服务提供者
A specific implementation of the SPI. The Service Provider contains one or more concrete classes that implement or extends the service type.
A Service Provider is configured and identified through a provider configuration file which we put in the resource directory META-INF/services. The file name is the fully-qualified name of the SPI and his content is the fully-qualified name of the SPI implementation.
The Service Provider is installed in the form of extensions, a jar file which we place in the application classpath, the java extension classpath or user-defined classpath.
不需要翻译了,简单的理解就是接口的实现,请看上面#2中的例子。Oracle开发的链接数据库的jar就是一个服务提供者。
4. ServiceLoader
At the heart of the SPI is the ServiceLoader class. This has the role of discovering and loading implementations lazily. It uses the context classpath to locate providers implementations and put them in an internal cache.
这个类ServiceLoader是SPI的核心。使用懒加载方式发现和加载服务的实现。他通过classpath的定位服务的实现,并将他们加载到jvm中。
举个例子
创建一个项目:SpiDemo(服务接口)
定义服务接口
package com.ian.demo.spi;
public interface MyService {
void sayHello();
}
打包并install安装到本地 .m2的路径下,pom.xml:
<groupId>com.ian.demo</groupId>
<artifactId>SpiDemo</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
另起一个新的项目:SpiDemoServicesProvider(服务提供者)
导入刚才install的jar包,pom.xml:
<dependencies>
<dependency>
<groupId>com.ian.demo</groupId>
<artifactId>SpiDemo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
实现服务接口:
public class MyServiceImpl implements MyService {
@Override
public void sayHello() {
System.out.println("Hi, There!");
}
}
打包安装到本地m2目录:
<groupId>com.ian.demo</groupId>
<artifactId>SpiDemoServicesProvider</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
另起一个项目调用接口:接口真正的使用者
main函数,ClassLoader加载接口实现
public class Main {
public static void main(String[] args) {
ServiceLoader<MyService> myServiceImplSet = ServiceLoader.load(MyService.class);
if(myServiceImplSet.iterator().hasNext()){
myServiceImplSet.iterator().next().sayHello();
}
}
}
导入上面的SPI和SPI实现jar:
<dependencies>
<dependency>
<groupId>com.ian.demo</groupId>
<artifactId>SpiDemoServicesProvider</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.ian.demo</groupId>
<artifactId>SpiDemo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
运行:
Hi, There!
Process finished with exit code
总结:
是不是很累赘,为啥要写三个项目?一个不就行了?还要用ServiceLoader是不是在故弄玄虚。。
当然不是。使用场景就如我上面Oracle的例子。咱们普通开发者要给公司做个项目,需要连接Oracle数据库,好在java给我们提供了连接接口,并且Oracle提供了实现,我们只要有jre和ojdbc的jar就可以了。有了SPI后,java和Oracle'的开发者就可以分工合作了。这是java典型的解构和强封装的特性。我们日常的开发中如果有多个系统合作开发的也可以这样进行。
Java SPI详细的例子的更多相关文章
- Java SPI 和 API,傻傻分不清?
最近新写了一个中间件「运行时动态日志等级开关」,其中使用Java SPI机制实现了自定义配置中心,保证良好的扩展性. 项目地址,走过路过可以点个star :)https://github.com/sa ...
- Wget下载终极用法和15个详细的例子
Wget下载终极用法和15个详细的例子 备注:wget 不支持https 下载,也没有相关https参数,当下载https的时候或以改用 axelWget是一种很好用的因特网下载工具,他具有的很多特 ...
- Java spi机制浅谈
最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现和接入都采用了java的spi机制. 所以简单的总结下java spi机制的思想. 我们系统里抽象的各个模块,往往有很多不同的实现方案,比 ...
- Java SPI机制和使用示例
JAVA SPI 简介 SPI 是 Java 提供的一种服务加载方式,全名为 Service Provider Interface.根据 Java 的 SPI 规范,我们可以定义一个服务接口,具体的实 ...
- Java SPI
一.什么是Java SPI? SPI的全名为Service Provider Interface.大多数开发人员可能不熟悉,因为这个是针对厂商或者插件的.在java.util.ServiceLoade ...
- 了解一下Java SPI的原理
了解一下Java SPI的原理 1 为什么写这篇文章? 近期,本人在学习dubbo相关的知识,但是在dubbo官网中有提到Java的 SPI,这个名词之前未接触过,所以就去看了看,感觉还是有很多地方有 ...
- fasttext的基本使用 java 、python为例子
fasttext的基本使用 java .python为例子 今天早上在地铁上看到知乎上看到有人使用fasttext进行文本分类,到公司试了下情况在GitHub上找了下,最开始是c++版本的实现,不过有 ...
- Dubbo 扩展点加载机制:从 Java SPI 到 Dubbo SPI
SPI 全称为 Service Provider Interface,是一种服务发现机制.当程序运行调用接口时,会根据配置文件或默认规则信息加载对应的实现类.所以在程序中并没有直接指定使用接口的哪个实 ...
- Java SPI 机制实现解耦与本地化
SPI 是 Java 提供的一种服务加载方式,全名为 Service Provider Interface,可以避免在 Java 代码中写死服务的提供者,而是通过 SPI 服务加载机制进行服务的注册和 ...
随机推荐
- 解读闭包,这次从ECMAScript词法环境,执行上下文说起
对于x年经验的前端仔来说,项目也做了好些个了,各个场景也接触过一些.但是假设真的要跟面试官敞开来撕原理,还是有点慌的.看到很多大神都在手撕各种框架原理还是有点羡慕他们的技术实力,羡慕不如行动,先踏踏实 ...
- Error:Failed to resolve: com.android.support:recyclerview-v7:28.0.0解决方法
在使用Android Studio的过程中需要添加依赖recyclerview,出现报错: Unable to resolve dependency for ':app@debug/compileCl ...
- 精讲RestTemplate第7篇-自定义请求失败异常处理
本文是精讲RestTemplate第7篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...
- 技术分享丨数据仓库的建模与ETL实践技巧
摘要:如何搭建数据仓库,在这个过程中都应该遵循哪些方法和原则,项目实践中有哪些技巧. 一.数据仓库的“心脏” 首先来谈谈数据模型.模型是现实世界特征的模拟和抽象,比如地图.建筑设计沙盘,飞机模型等等. ...
- 《Java从入门到失业》第一章:计算机基础知识(一):二进制和十六进制
0 前言 最近7年来的高强度工作和不规律的饮食作息,压得我有些喘不过气,身体也陆续报警.2018年下半年的一场病,让我意识到了这个问题的严重性,于是开始强制自己有规律饮食和作息,并辅以健身锻炼,不到2 ...
- python列表的增删改查和嵌套
列表 python常用的数据类型 可承载任意的数据类型 列表是有序的,可索引.切片(步长) 列表的创建 list1 = [1, 2, 'whll'] #1. list2 = list() #2. #3 ...
- docker入门1-docker container
image和container介绍 一个image是一个可被docker执行的包,它包括程序运行的所有东西,包括代码,运行时,库,环境变量和配置文件. 一个container是image在内存中的运行 ...
- Vue Axios 的封装使用
目录 Axios 说明 安装 Axios 请求配置 响应结构 常用请求方法 默认值配置 全局的 请求配置项 自定义实例默认值 配置的优先顺序 拦截器 个人完整 axios 配置 Axios 说明 Ax ...
- LINUX进程ps -ef和ps -aux的区别及格式详解
Linux下显示系统进程的命令ps,最常用的有ps -ef 和ps aux.这两个到底有什么区别呢?两者没太大差别,讨论这个问题,要追溯到Unix系统中的两种风格,System V风格和BSD 风格, ...
- Apache Hudi 0.6.0版本重磅发布
1. 下载信息 源码:Apache Hudi 0.6.0 Source Release (asc, sha512) 二进制Jar包:nexus 2. 迁移指南 如果您从0.5.3以前的版本迁移至0.6 ...