Java SPI(Service Provider Interface)基础原理

493 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

1、Java SPI概念

Java SPI是目前Java主流框架中使用到的核心思想,如果你之前没有学习过框架,那么先看一下Java SPI的概念,更有利于后面框架的学习,能够学习到一些框架设计的原理和精髓;如果你已经学习过矿建,那么再看一遍Java SPI会让你对框架的学习有更深一步的思考。

SPI: 全称是 Service Provider Interface;

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

一个标准的SPI,由3个组件构成,分别是:

  • Service
  • Service Provider.
  • ServiceLoader

1.1、Java SPI的概念和术语

1.2、Java SPI的运行流程

Application 应用程序使用 ServiceLoader 的 load 方法加载 Service 服务接口的实现类,Application 应用程序只需要和Service接口交互,不需要关注Service的具体实现,是面向Service的接口编程。

1.3、Java SPI原理

以JDBC为例介绍Java SPI

1.3.1、JDBC简介

1.3.2、Java SPI出现之前,JDBC使用

1.3.3、Java SPI在JDBC中使用的演变流程

但是如果厂商提供了配置文件,那如何读取这些配置文件呢?

1.3.4、应用Java SPI思想之后的JDBC使用

这样做的一个 好处 就是:如果需要更换数据库驱动,那么不需要再去更改具体代码,只需要更换对应的jar包即可。降低了代码的耦合度,更方便维护。

1.3.5、Java SPI的三大规范要素

1、规范的配置文件

  • 文件路径: 必须在JAR包中的 META-INF/services 目录下
  • 文件名称: Service 接口的全限定名
  • 文件内容: Service 实现类 (即Service Provider类)的全限定名。如果有多个实现类,那么每一个实现类在文件中单独占据一行

JDBC例子中对应mysql-connector-java-0.0..28.jar对应的配置文件内容,如下:

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

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

JDBC中Service Provider类中的无参构造方法,如下:

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

  • 方式一:将 Service Provider 的 JAR 包放到 classpath 中 (最常用)
  • 方式二:将JAR 包安装到 JRE 的扩展目录中;
  • 方式三: 自定义一个 ClassLoader;

例如以Maven方式引入jar包,如下:

1.3.6、Java SPI构建流程

JavaSPI 实际上是 “基于接口的编程+策略模式+配置文件” 组合实现的动态加载机制。具体而言:

  • STEP1. 定义一组接口, 假设是 autocomplete.PrefixMatcher;

  • STEP2. 写出接口的一个或多个实现(autocomplete.EffectiveWordMatcher, autocomplete.SimpleWordMatcher);

  • STEP3. 在 src/main/resources/ 下建立 /META-INF/services 目录, 新增一个以接口命名的文件 autocomplete.PrefixMatcher, 内容是要应用的实现类全限定名(autocomplete.EffectiveWordMatcher 或 autocomplete.SimpleWordMatcher 或两者),一个实现类的全限定名占一行;

  • STEP4. 使用 ServiceLoader 来加载配置文件中指定的实现。

1.3.7、Java SPI小结

作用

  • 提供了一种组件发现和注册的方式,可以用于实现各种插件,或者灵活替换框架所使用的组件。

优点

  • 基于面向接口编程,优雅地实现模块之间的解耦

设计思想

  • 面向接口 + 配置文件 + 反射技术,YYDS!!!

应用场景

  • JDBC、SLF4J、Servlet容器初始化,等等

1.4、构建一个Java SPI实例

1.5、Java SPI应用 -> SpringBoot自动配置

SpringBoot项目默认会自动扫描当前项目的package,将其中的配置类注入到IoC容器中,但是在与其它框架集成的时候,则不能直接扫描注入,则需要Auto-Cofiguration进行配置,即自动的将jar包对应的配置类注入到IoC容器中。

1.5.1、Auto-Configuration实现

1.5.2、Java SPI的设计思想

1.5.3、SpringBoot自动配置核心流程

参考

www.bilibili.com/video/BV1RY…