博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java的SPI机制与简单的示例
阅读量:4261 次
发布时间:2019-05-26

本文共 2436 字,大约阅读时间需要 8 分钟。

一、SPI机制

这里先说下SPI的一个概念,SPI英文为Service Provider Interface单从字面可以理解为Service提供者接口,正如从SPI的名字去理解SPI就是Service提供者接口;我对SPI的定义:提供给服务提供厂商与扩展框架功能的开发者使用的接口。

在我们日常开发的时候都是对问题进行抽象成Api然后就提供各种Api的实现,这些Api的实现都是封装与我们的Jar中或框架中的虽然当我们想要提供一种Api新实现时可以不修改原来代码只需实现该Api就可以提供Api的新实现,但我们还是生成新Jar或框架(虽然可以通过在代码里扫描某个目录已加载Api的新实现,但这不是Java的机制,只是hack方法),而通过Java SPI机制我们就可以在不修改Jar包或框架的时候为Api提供新实现。

     很多框架都使用了java的SPI机制,如java.sql.Driver的SPI实现(mysql驱动、oracle驱动等)、common-logging的日志接口实现、dubbo的扩展实现等等框架;

 

SPI机制的约定:

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

2)         使用ServiceLoader类动态加载META-INF中的实现类

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

4)         Api具体实现类必须有一个不带参数的构造方法

                                SPI机制结构图

二、SPI机制示例

 

                        实例结构图

IOperation接口:

1
2
3
4
5
6
7
8
/**
 
* Created by LX on 2015/3/8.
 
*/
public 
interface 
IOperation {
 
    
public 
int 
operation(
int 
numberA, 
int 
numberB);
 
}

PlusOperationImpl实现:

1
2
3
4
5
6
7
8
9
10
11
12
import 
co.solinx.demo.api.IOperation;
 
/**
 
* Created by LX on 2015/3/8.
 
*/
public 
class 
PlusOperationImpl 
implements 
IOperation {
 
    
@Override
    
public 
int 
operation(
int 
numberA, 
int 
numberB) {
        
return 
numberA + numberB;
    
}
}

SPI接口的实现类:DivisionOperationImpl

1
2
3
4
5
6
7
8
9
10
11
12
import 
co.solinx.demo.api.IOperation;
 
/**
 
* Created by LX on 2015/3/8.
 
*/
public 
class 
DivisionOperationImpl 
implements 
IOperation {
 
    
@Override
    
public 
int 
operation(
int 
numberA, 
int 
numberB) {
        
return 
numberA / numberB;
    
}
}

META-INF/Services目录中的文件:

文件名:co.solinx.demo.api.IOperation,内容:co.solinx.demo.spi.DivisionOperationImpl

Main类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import 
co.solinx.demo.api.IOperation;
import 
co.solinx.demo.impl.PlusOperationImpl;
import 
co.solinx.demo.spi.DivisionOperationImpl;
 
import 
java.util.Iterator;
import 
java.util.ServiceLoader;
 
/**
 
* Created by LX on 2015/3/8.
 
*/
public 
class 
main {
 
    
public 
static 
void 
main(String[] args) {
        
IOperation plus = 
new 
PlusOperationImpl();
 
        
IOperation division = 
new 
DivisionOperationImpl();
        
System.out.println(plus.operation(
5
3
));
 
        
System.out.println(division.operation(
9
3
));
 
        
ServiceLoader<IOperation> operations = ServiceLoader.load(IOperation.
class
);
        
Iterator<IOperation> operationIterator = operations.iterator();
        
System.out.println(
"classPath:"
+System.getProperty(
"java.class.path"
));
        
while 
(operationIterator.hasNext()) {
            
IOperation operation = operationIterator.next();
            
System.out.println(operation.operation(
6
3
));
        
}
    
}
}

运行结果:

 

如把SPI实现打包为jar需要把jar放在classpath目录中,SPI jar包运行结果:

jdbc 中的例子:

 

你可能感兴趣的文章
Paxos协议学习---3.Paxos Made Simple
查看>>
C/C++输入输出
查看>>
泸州NGN属南气矿工程----华为s2600磁盘阵列问题解决
查看>>
泸州属南气矿----配置S2600磁盘阵列报错:There is no master controller.
查看>>
SQL 调优1
查看>>
OA报账规范(出差专用)
查看>>
生产库快速关闭数据库
查看>>
差异增量备份和累积增量备份的差别
查看>>
ASM 无法发现候选磁盘组----grid 11.2.0.3 asm 自检通不过 prvf-5184
查看>>
ASM 无法发现候选磁盘组----丢失的ASM磁盘组 ASM的磁盘组无法挂载
查看>>
Oracle 10g配置单向stream流复制,完整记录
查看>>
ORA-00845 MEMORY_TARGET not supported on this system
查看>>
ORA-00257: archiver error --11GR2 RAC 设置归档路径和开启flashback
查看>>
奕新集团项目--Oracle 源RAC ---目标 RAC GG 搭建 11.2.3 版本 双向同步
查看>>
What is SCAN in Oracle 11g R2 RAC
查看>>
关于Recycle Bin是什么以及实验
查看>>
Linux搭建时间同步服务器
查看>>
ORA-12541: TNS:no listener
查看>>
mysql数据库存储路径更改 数据文件位置
查看>>
Could not fetch specs from https://rubygems.org/
查看>>