彻底讲明白Java SPI

彻底讲明白Java SPI,第1张

彻底讲明白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..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中的配置文件
举个栗子:


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/868383.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存