彻底讲明白Java SPI

彻底讲明白Java SPI

1. 什么是SPI?

SPI:Service Provider Interface
它是从java 6 开始引入的,是一种基于classLoader来发现并加载服务的机制
一个标准的SPI,由三个组件构成,分别是:

  1. service
    service:是一个公开的借口和抽象类,定义了一个抽象的功能模块。
  2. service provider
    service provider:是service接口的实现类。
  3. serviceLoader
    serviceLoader:是SPI机制中的核心组件,负责在运行时发现并加载service Provider。对应的是JDK中serviceLoader类,调用他load方法,就可在运行时发现和加载service provider
    在这里插入图片描述
    上面的图介绍了SPI运行流程,application程序开始,使用serviceLoader加载provider(第三方家jar包中的service provider,service provider实现了service 接口,jar包中可以实现多个serivce provider,application并不关心实现类的逻辑,只关心通过service接口返回他想要的结果)。

2.SPI有什么用?

Java SPI在JDBC中应用
JDBC,全称Java DataBase Connectivity

  • JDBC是使用java语言来访问数据库的一套API
  • 每个数据库厂商都会提供各自JDBC实现
    在这里插入图片描述
    我们来看看JDBC的流程
    在这里插入图片描述
    1、在Java SPI出现之前,我们是怎样来使用JDBC的:
//1.加载驱动(使用Class.forName方法)
Class.forName("com.mysql.jdbc.Driver");
//2.打开数据库连接
connection conn = DriverManager.getConnection(url,user,password);
//3.执行SQL语句(使用Statement类)
Statment st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from table_user limit 1");
//4.处理结果集(使用ResultSet类)
while(rs.next()){
	System.out.printLn(rs.getInt("id"));
}
//5.关闭连接
rs.close();
st.close();
conn.close();

在加载驱动时,程序员们使用Class.forName来加载驱动,
mysql使用Class.forName(“com.mysql.jdbc.Driver”),
而oracle使用Class.forName(“orcle.jdbc.driver.OracleDriver”),
SQLServer使用Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”)
这样采用硬编码方式耦合性太高,我们可以将驱动类型写入到第三方jar包配置文件中,这样可能会好一点。只需要引入jar包就可以直接使用了,这不就是我们的SPI机制吗。

SPI出现后我们怎么使用呢?

//1.引入数据库驱动Jar包(例如mysqljar包,mysql-connector-java.<version>.jar)
//2.打开数据库连接
connection conn = DriverManager.getConnection(url,user,password);
//3.执行SQL语句(使用Statement类)
Statment st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from table_user limit 1");
//4.处理结果集(使用ResultSet类)
while(rs.next()){
	System.out.printLn(rs.getInt("id"));
}
//5.关闭连接
rs.close();
st.close();
conn.close();

SPI的三大要素

  1. 规范的配置文件
  • 文件路径:必须在JAR包中的META-INF/service目录下

  • 文件名称:service接口的全限定名

  • 文件内容:Service实现类(即Service Provider类)的权限定名。如果有多个实现类,每一个实现类在文件中单独占据一行

在这里插入图片描述

  1. Service Provider类必须具备无参的默认方法
    Service接口的实现类,即Service Provider类,必须具备无参的默认构造方法。因为随后通过技术实例化他时,时不带参数的。
  2. 保证能加载到配置文件和Service Provider类:
    方式一:将Service Provider的JAR包放在classpath中(最常用)
    方式二:将JAR包安装到JRE的拓展目录中
    方式三:自定义一个ClassLoader

举个栗子:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Java SPI的设计思想

1.使用约定的配置文件
2.谁提供jar包,也负责提供配置文件:该内聚低耦合,代码+配置
3.使用ClassLoader的getResource和getResources方法,来读取classpath的配置文件

我们来看看SpringBoot的自动配置

SpringBoot的自动配置核心实现:
1、使用约定的配置文件:

  • 文件路径是MEAT-INF/spring.factories
  • 文件内容是"key=value1,value2,…"的格式。其中key是"EnableAutoConfigration"的类名,value为自动配置的类名

2、提供自动配置类的jar包中,也同时提供配置文件MEAT-INF/spring.factories

3、和SPI一样:使用ClassLoader的getResource和getResources方法来读取classpath中的配置文件
举个栗子:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值