文档章节

java SPI机制的初步学习

独钓渔
 独钓渔
发布于 2017/04/14 01:53
字数 1087
阅读 84
收藏 1

java SPI机制的初步学习

1. SPI机制

SPI的全名为Service Provider Interface.大多数开发人员可能不熟悉,因为这个是针对厂商或者插件的。在java.util.ServiceLoader的文档里有比较详细的介绍。简单的总结下java spi机制的思想。我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块、jdbc模块的方案等。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。 java spi就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。

 

2. SPI具体约定

java spi的具体约定为:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

 

入门实验:

tspi这个为接口包

alogger这个为ALogger实现tspi的实现包

blogger这个为BLogger实现tspi的实现包

tspiTest这个项目为测试包

把这4个做成4个单独的项目

 

(1) tspi项目(接口项目)

新建一个Logger的接口分别有debug,info,warn,error这4个方法。

package com.imddy.tspi;

public interface Logger {

	public void debug(String logger);
	
	public void info(String logger);
	
	public void warn(String logger);
	
	public void error(String logger);
	
}

在来个工具类LoggerFactory来获取Logger,(这里就使用了spi机制)

package com.imddy.tspi;

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

public class LoggerFactory {

	public LoggerFactory() {
		
	}
	
	public static Logger getLogger() {
		
		Logger logger = null;
		
		ServiceLoader<Logger> serviceLoader = ServiceLoader.load(Logger.class);
		Iterator<Logger> loggers = serviceLoader.iterator();
		if (loggers.hasNext()) {
			logger = loggers.next();
		}
		
		return logger;
	}
	
}

 

这个项目到包成jar 由于没有什么依赖,pom.xml基本是默认内容。

 

(2)alogger项目(A实现项目)

这里有个ALogger为Logger的实现类:

package com.imddy.alogger;

import com.imddy.tspi.Logger;

public class ALogger implements Logger{
	
	public ALogger() {
		
	}

	public void debug(String logger) {
		System.out.println("ALogger-->debug: " + logger);
	}

	public void info(String logger) {
		System.out.println("ALogger-->info: " + logger);	
	}

	public void warn(String logger) {
		System.out.println("ALogger-->warn: " + logger);
	}

	public void error(String logger) {
		System.out.println("ALogger-->error: " + logger);
	}

}

在资源目录下创建 ”META-INF/Services目录” 在这个目录下,新建一个为 “com.imddy.tspi.Logger” 的文件(接口全限定名称),其内容为 “com.imddy.alogger.ALogger” (实现类全限定名称)

pom.xml中需要依赖接口项目,这个项目也是打包成一个jar包。

 

(3)blogger项目(B实现项目)

这里有个BLogger为Logger的实现类:

package com.imddy.blogger;

import com.imddy.tspi.Logger;

public class BLogger implements Logger{
	
	public BLogger() {
		
	}

	public void debug(String logger) {
		System.out.println("BLogger-->debug: " + logger);
	}

	public void info(String logger) {
		System.out.println("BLogger-->info: " + logger);	
	}

	public void warn(String logger) {
		System.out.println("BLogger-->warn: " + logger);
	}

	public void error(String logger) {
		System.out.println("BLogger-->error: " + logger);
	}

}

在资源目录下创建 ”META-INF/Services目录” 在这个目录下,新建一个为 “com.imddy.tspi.Logger” 的文件(接口全限定名称),其内容为 “com.imddy.blogger.BLogger” (实现类全限定名称)

pom.xml中需要依赖接口项目,这个项目也是打包成一个jar包。

 

(4)tspiTest项目 (测试项目)

pom.xml中的依赖添加:

        <dependency>
			<groupId>com.imddy</groupId>
			<artifactId>tspi</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<!-- <dependency>
			<groupId>com.imddy</groupId>
			<artifactId>alogger</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency> -->
		<dependency>
			<groupId>com.imddy</groupId>
			<artifactId>blogger</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

写代码只需要接口项目依赖,运行是有pathclass有A实现就使用A实现,有B实现就使用B实现。

测试代码如下:

package com.imddy.tspiTest;

import com.imddy.tspi.Logger;
import com.imddy.tspi.LoggerFactory;

public class App {
	
	private static Logger logger = LoggerFactory.getLogger();
	
	public static void main(String[] args) {
		
		logger.debug("this is use debug... ");
		
		logger.info("this is use info... ");
		
		logger.warn("this is use warn... ");
		
		logger.error("this is use error... ");
		
	}
}

 

运行效果如图:

© 著作权归作者所有

独钓渔
粉丝 48
博文 385
码字总数 148158
作品 0
沙坪坝
系统管理员
私信 提问
高级开发必须理解的Java中SPI机制

本文通过探析JDK提供的,在开源项目中比较常用的Java SPI机制,希望给大家在实际开发实践、学习开源项目提供参考。 一、SPI是什么 SPI全称Service Provider Interface,是Java提供的一套用来...

技术小能手
2018/09/14
0
0
Java SPI - Service Provider Interface

Java SPI_Service Provider Interface 最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现和接入都采用了java的spi机制。所以简单的总结下java spi机制的思想。 我们系统里抽象...

秋风醉了
2015/12/29
0
0
我是SPI,我让框架更加优雅了!

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

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

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

中间件小哥
2018/05/29
0
0
聊聊Dubbo - Dubbo可扩展机制实战

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

阿里云云栖社区
2018/06/04
0
0

没有更多内容

加载失败,请刷新页面

加载更多

JWT学习总结

官方 https://jwt.io 英文原版 https://www.ietf.org/rfc/rfc7519.txt 或 https://tools.ietf.org/html/rfc7519 中文翻译 https://www.jianshu.com/p/10f5161dd9df 1. 概述 JSON Web Token(......

冷基
今天
4
0
AOP的学习(1)

AOP 理解AOP编程思想(面向方法、面向切面) spring AOP的概念 方面 -- 功能 目标 -- 原有方法 通知 -- 对原有方法增强的方法 连接点 -- 可以用来连接通知的地方(方法) 切入点 -- 将用来插入...

太猪-YJ
今天
4
0
一张图看懂亮度、明度、光度、光亮度、明亮度

亮度、明度、光亮度,Luminance和Brightness、lightness其实都是一个意思,只是起名字太难了。 提出一个颜色模型后,由于明度的取值与别人的不同,为了表示区别所以就另想一个词而已。 因此在...

linsk1998
昨天
11
0
Python应用:python链表示例

前言 python链表应用源码示例,需要用到python os模块方法、函数和类的应用。 首先,先简单的来了解下什么是链表?链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是...

python小白1
昨天
5
0
Source Insight加载源码

Source Insight是一个图形化的源代码查看工具(当然也可以作为编译工具)。如果一个项目的源代码较多,此工具可以很方便地查找到源代码自建的依赖关系。 1.创建工程 下图为Snort源代码的文件...

天王盖地虎626
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部