开启掘金成长之旅!这是我参与「掘金日新计划 · 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自动配置核心流程
参考