我是靠谱客的博主 清新电灯胆,这篇文章主要介绍SPI(Service Provider Interface)机制及SPI在springMVC的应用,现在分享给大家,希望可以做个参考。

什么是SPI

SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类, 整体机制如下图:

在这里插入图片描述

Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制,

服务的接口标准的定义,然后服务接口的实现通过SPI机制在META-INF/services暴露自己的接口的实现。

使用介绍

要使用Java SPI,需要遵循如下约定:

  • 1、当服务提供者提供了接口的一种具体实现后,在jar包的META-INF/services目录下创建一个以“接口全限定名”为命名的文件,内容为实现类的全限定名
  • 2、接口实现类所在的jar包放在主程序的classpath中;
  • 3、主程序通过java.util.ServiceLoder动态装载实现模块,它通过扫描META-INF/services目录下的配置文件找到实现类的全限定名,把类加载到JVM;
  • 4、SPI的实现类必须携带一个不带参数的构造方法

具体demo

标准服务接口提供方

  1. 先新建工程,新建模块spi-db-interface
    在这里插入图片描述

  2. 定义标准接口

    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /** * @author fangYaJun * @date 2021/7/29 10:29 */ public interface DbInterface { /** * 保存数据接口 * @param data */ public void saveData(String data); }

服务提供方1(对接口标准的具体实现)

  1. 新建模块spi-db-mysql-impl,如下截图
    在这里插入图片描述

  2. 对标准接口的实现

    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package com.spi.mysql; import com.spi.db.myinterface.DbInterface; /** * @author fangYaJun * @date 2021/7/29 10:36 */ public class MySqlSpiTest implements DbInterface { @Override public void saveData(String data) { System.out.println("MySqlSpiTest保存了数据:" + data); } }
  3. 在META-INF/services目录下创建一个以“接口全限定名”为命名的文件,内容为实现类的全限定名
    在这里插入图片描述

服务提供方2

  1. 新建模块spi-db-redis-impl,如下截图
    在这里插入图片描述

  2. 实现标准服务接口

    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /** * @author fangYaJun * @date 2021/7/29 10:48 */ public class RedisSpiImpl implements DbInterface { @Override public void saveData(String data) { System.out.println("RedisSpiImpl 保存了" + data); } }
  3. 在META-INF/services目录下创建一个以“接口全限定名”为命名的文件,内容为实现类的全限定名
    在这里插入图片描述

测试工程

  1. 新建测试模块
    在这里插入图片描述

  2. pom引入接口模块,具体实现模块的依赖

    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <dependencies> <dependency> <groupId>com.spi.db</groupId> <artifactId>spi-db-interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.spi.db</groupId> <artifactId>spi-db-mysql-impl</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>com.spi.db</groupId> <artifactId>spi-db-redis-impl</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
  3. 测试类

    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    /** * @author fangYaJun * @date 2021/7/29 11:04 * * 1、 ServiceLoader:load()指定一个接口, * 他就会加载当前系统里面所有的这个接口的【指定实现】 * 2、SPI(Service Provider Interface) * 接口工程---提供接口 * ---- 实现工程1 : 实现接口 【META-INF/services 创建文件 接口名作为文件名 实现类全路径作为文件内容】 * ---- 实现工程2 : 实现接口 * 客户端----引用 工程1、或者 工程2 */ public class SpiAppTest { public static void main(String[] args) { ServiceLoader<DbInterface> load = ServiceLoader.load(DbInterface.class); for (DbInterface dbInterface : load) { dbInterface.saveData("我是数据"); } } }

    运行结果:
    在这里插入图片描述

从结果中我们看出了,通过spi机制,测试类只需要通过ServiceLoader.load(DbInterface.class) 加载对应的类名,我们就可以获取到全部实现了DbInterface接口的对象,调用DbInterface接口定义的方法,我们就可以运行具体实现类实现了DbInterface接口的方法。

SPI在springMVC的应用

我们来看spring-web项目

在这里插入图片描述

从截图我们可以看出spring-web项目META-INF有SPI机制
javax.servlet.ServletContainerInitializer的规范实现了

复制代码
1
2
org.springframework.web.SpringServletContainerInitializer

我们来看看 ServletContainerInitializer,这是java官方定义的servlet 规范:
在这里插入图片描述

而SpringServletContainerInitializer 是spring官方对ServletContainerInitializer规范的实:
在这里插入图片描述

综上所诉,tomcat在启动的时候,会加载ServletContainerInitializer类,通过SPI机制,进而调用SpringServletContainerInitializer 的 onStartup方法来加载springweb项目

最后

以上就是清新电灯胆最近收集整理的关于SPI(Service Provider Interface)机制及SPI在springMVC的应用的全部内容,更多相关SPI(Service内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(128)

评论列表共有 0 条评论

立即
投稿
返回
顶部