一、Java SPI 概述

SPI:Service Provider Interface

它是从java 6开始引入的,是一种基于 ClassLoader 来 发现并加载服务的机制

一个标准的SPI,由三个组件构成:

  • Service: 是一个公开的接口或抽象类,定义了一个抽象的功能模块
  • Service Provider: 是Service接口的一个实现类
  • Service Loader: 是SPI机制中的核心组件,负责在运行时发现并加载Service Provider

二、Java SPI 运行流程

1-JavaSPI的运行流程.png

三、Java SPI 的应用

1、在JDBC中的应用

JDBC:Java DataBase Connectivity

  • JDBC即使用Java语言来访问数据库的一套API
  • 每个数据库厂商会提供各自的JDBC实现

2-JDBC结构.png

2、JDBC执行流程

3-JDBC执行流程.png

3、Java SPI之前的JDBC使用

  • 加载数据库驱动
// 加载 Mysql 数据库驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 加载 Oracle 数据库驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
// 加载 SqlServer 数据库驱动
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
  • Mysql具体实例
// 1.加载驱动(使用Class.forName方法反射)
Class.forName("com.mysql.cj.jdbc.Driver");
// 2.获取数据库连接对象
String url = "jdbc:mysql://localhost:3306/数据名称?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC";
String userName = "root";
String passWrod = "root";
// 3.调用方法,获取数据库连接对象
Connection connection = DriverManager.getConnection(url, userName, passWrod);
// 4.获取执行SQL语句的Statement对象
Statement statement = connection.createStatement();
//定义SQL语句
String sql = "INSERT INTO account values(NULL,'九九',2000) ";
//Statement对象调用executeUpdate方法执行sql语句,获取结果
int reeult = statement.executeUpdate(sql);
if (reeult > 0) {
    System.out.println("添加成功");
} else {
    System.out.println("添加失败");
}
//关闭资源
statement.close();
connection.close();

4、Java SPI演化

4-SPI演化png.png

四、Java SPI的三大规范要素

1、规范的配置文件:

  • 文件路径: 必须在JAR包中META-INF/services目录下

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

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

  • 在JDBC中的对应实现

5-Mysql驱动解压.png

2、Service Provider类必须具备无参的默认构造方法:

  • Service接口的实现类,即Service Provider类,必须具备无参的默认构造方法。因为随后通过反射技术实例化它时,是不带参数的。

  • 在JDBC中的对应实现

6-Mysql的Driver类.png

3、保证能加载到配置文件和Service Provider类

  • 方式一: 将Service Provider的JAR包放到classpath中(最常用)

  • 方式二: 将JAR包安装到JRE的扩展目录中

  • 方式三: 自定义一个ClassLoader

  • 在JDBC中的对应实现

7-MAVEN引入Mysql驱动包.png

五、小结

  • 作用:
    • 提供了一中组件发现和注册的方式,可以用于实现各种插件,或者灵活替换框架所使用的组件
  • 优点:
    • 基于面向接口编程,优雅地实现模块之间的解耦
  • 设计思想:
    • 面向接口+配置文件+反射技术
  • 应用场景
    • JDBC、SLF4J、Servlet容器初始化等等

六、Java SPI 与SpringBoot自动配置

8-javaspi与SpringBoot自动配置.png

1、Auto-Configuration

实现Auto-Configuration的前提:

  • 首先,不能脱离SpringBoot框架
    • 可以继续使用@Configuration等已有注解
  • 其次,对用户友好,将“全自动”贯彻到底
    • 参考Java SPI的设计思想

2、Java SPI的设计思想与SpringBoot自动配置的核心实现

9-javaspi与自动配置的核心实现.png

3、具体案例

  • 我们来展示一个Mybatis自动配置的案例

10-Mybatis自动配置.png

4、简单总结SpringBoot自动配置流程

11-SpringBoot自动配置流程.png