SPI(服务提供发现机制)简单使用

news2024/11/18 12:33:27

一、概述

SPI的英文全称是Service Provider Interface,是Java内置的一种服务提供发现机制。一般常用于一些框架或组件库的开发,我们最熟悉JDBC就应用到了SPI机制,并且在Spring、Dubbo中也大量应用了SPI机制。SPI机制是针对同一个接口采用不同的实现,提供给不同的用户使用,目的就是为了提高框架或者组件库的扩展性。

二、Java中SPI的实现

代码示例:

  • 创建ide开发工具的插件接口
package com.ideax.spi.jdk;

/**
 * <p>
 * Idea插件接口
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public interface IdePluginSpi {
    void plugin();
}
  • 为Goland开发插件
package com.ideax.spi.jdk;

/**
 * <p>
 * Goland插件实现类
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public class GolandPlugin implements IdePluginSpi {
    @Override
    public void plugin() {
        System.out.println("goland plugin");
    }
}
  • 为Webstorm开发插件
package com.ideax.spi.jdk;

/**
 * <p>
 * Webstorm插件实现类
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public class WebstormPlugin implements IdePluginSpi {
    @Override
    public void plugin() {
        System.out.println("webstorm plugin");
    }
}
  • 以Springboot工程为例,在项目的resources目录下新建META-INF/services/目录,在该目录下创建com.ideax.spi.jdk.IdePluginSpi文件,文件中按照如下格式,写入接口的多个实现类全路径
com.ideax.spi.jdk.WebstormPlugin
com.ideax.spi.jdk.GolandPlugin
  • 测试代码
package com.ideax.spi.jdk;

import java.util.ServiceLoader;

/**
 * <p>
 * jdk中的spi测试
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public class JdkSpiTest {
    public static void main(String[] args) {
        ServiceLoader<IdePluginSpi> serviceLoader = ServiceLoader.load(IdePluginSpi.class);
        serviceLoader.forEach(IdePluginSpi::plugin);
    }
}
  • 运行结果
    在这里插入图片描述
    说明: Java内置的SPI实现时,要通过java.util.ServiceLoader类,解析项目以及jar文件classPath下META-INF/services/目录中,且以接口全路径命名的文件,同时加载该文件中指定的该接口的实现类,通过这种方式,实现对指定接口实现类的调用。

三、Spring中SPI的实现

代码示例:

  • 创建一个数据库链接接口
package com.ideax.spi.spring;

/**
 * <p>
 * 数据库链接接口
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public interface DatabaseSpi {
    void getConnection();
}
  • PostgreSql实现类
package com.ideax.spi.spring;

/**
 * <p>
 * PostgreSql实现类
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public class PostgreSqlDatabase implements DatabaseSpi {
    @Override
    public void getConnection() {
        System.out.println("this database is PostgreSql");
    }
}
  • MySql实现类
package com.ideax.spi.spring;

/**
 * <p>
 * MySql实现类
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public class MySqlDatabase implements DatabaseSpi {
    @Override
    public void getConnection() {
        System.out.println("this database is MySql");
    }
}
  • 创建一个缓存链接接口
package com.ideax.spi.spring;

/**
 * <p>
 * 缓存链接接口
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public interface CacheSpi {
    void getConnection();
}
  • Memecache实现类
package com.ideax.spi.spring;

/**
 * <p>
 * Memecache实现类
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public class MemecacheCache implements CacheSpi {
    @Override
    public void getConnection() {
        System.out.println("this cache is memecache");
    }
}
  • Redis实现类
package com.ideax.spi.spring;

/**
 * <p>
 * redis实现类
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public class RedisCache implements CacheSpi {
    @Override
    public void getConnection() {
        System.out.println("this cache is redis");
    }
}
  • 以Springboot工程为例,在项目的resources目录下新建META-INF目录,在该目录下创建spring.factories文件,文件中按照如下格式,写入接口的多个实现类全路径
com.ideax.spi.spring.DatabaseSpi=\
com.ideax.spi.spring.MySqlDatabase,\
com.ideax.spi.spring.PostgreSqlDatabase

com.ideax.spi.spring.CacheSpi=\
com.ideax.spi.spring.RedisCache,\
com.ideax.spi.spring.MemecacheCache
  • 测试代码
package com.ideax.spi.spring;

import org.springframework.core.io.support.SpringFactoriesLoader;

import java.util.List;

/**
 * <p>
 * Spring中的Spi测试
 * </p>
 *
 * @author zhangxs
 * @since 2023-02-16
 */
public class SpringSpiTest {
    public static void main(String[] args) {
        List<DatabaseSpi> databaseSpis = SpringFactoriesLoader
                .loadFactories(DatabaseSpi.class, Thread.currentThread().getContextClassLoader());
        databaseSpis.forEach(DatabaseSpi::getConnection);

        List<CacheSpi> cacheSpis = SpringFactoriesLoader
                .loadFactories(CacheSpi.class, Thread.currentThread().getContextClassLoader());
        cacheSpis.forEach(CacheSpi::getConnection);
    }
}
  • 运行结果
    在这里插入图片描述
    说明: Spring中的SPI,类似于Java中SPI的设计理念,并且在其基础上进行了扩展,服务提供接口不再要求必须放到META-INF/services/目录下,Spring中是通过配置spring.factories方式实现SPI机制的。通过该机制,我们也可以在不修改Spring源码的前提下,根据我们的需求,扩展Spring框架。

四、总结

两种实现SPI的方式非常类似,我们可以根据需求自行选择,二者最明显的区别在于:

  • Java中的SPI,每一个服务提供接口只能对应一个配置文件,配置文件中存放当前接口的所有实现类全路径,多个服务提供接口就必须对应多个配置文件,所有配置都必须放在META-INF/services/目录下。
  • Spring中的SPI,只需要spring.factories一个配置文件,其中通过key-value的方式配置多个接口及其实现类,以接口全路径作为key,实现类全路径作为value,多个实现类直接用英文逗号隔开即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/349732.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

质量小议18 -- 熵

未能深入理解其包含的物理意义&#xff0c;浅记于此&#xff0c;以求理解对抗有自然无序的过程。 熵&#xff0c;对系统无序程序的度量&#xff0c;表征系统混乱程度。系统总是由有序向无序&#xff0c;最后走向静寂。 关键词&#xff1a;1. 无序和混乱&#xff1b;2. 有序向无…

Java中static关键字和代码块的学习

本文介绍了Java中static关键字的使用,即静态成员变量和成员方法以及使用,静态与非静态成员变量和方法的对比总结 Java中的代码块介绍与最后结合代码块和构造方法后的初始化代码执行顺序的练习 static和代码块的学习三.认识static关键字1.static修饰成员变量2.static修饰成员方法…

GAMES101-计算机图形学入门 LEC4: TRANSFORMATION-3D

本节课程视频地址&#xff1a;https://www.bilibili.com/video/BV1X7411F744/?p4 补充上一节课的一个内容&#xff0c;旋转矩阵的逆矩阵是它的转置&#xff0c;也就是说有R−θRθ−1RθTR_{-\theta} R_\theta^{-1}R_\theta^TR−θ​Rθ−1​RθT​ 上节课讲了&#xff0c;…

【go】结合一个go开源项目分析谷歌浏览器cookie为什么不安全 附go项目导包失败怎么解决教程

本文创作背景 源于谷歌浏览器提示密码被泄露 并且某站很快收到了异地企图登录的提醒。 当即怀疑是不是谷歌浏览器保存的密码不安全&#xff0c;最后查阅诸多资料 并找到一个go语言编写的开源项目进行研究&#xff0c;虽然最终不能确定密码是如何泄露的 但研究结论还是让人不由感…

在华为MateBook Ego的arm windows 11上安装hyper-V虚拟机

入手一台华为matebook Ego的笔记本&#xff0c;由于想要测试一些arm的驱动功能&#xff0c;经常会把系统搞蓝屏&#xff0c;于是想安装一个虚拟机&#xff0c;于是试了vmware ,visual-box&#xff0c;由于本机是arm架构上面两个软件都无法进行正常安装&#xff0c;可能是由于有…

Excel+SQL实战项目 - 餐饮业日销售情况分析仪

目录1、要完成的任务2、认识数据3、SQL数据加工4、excel形成分析仪1、要完成的任务 目标&#xff1a;结合SQL和excel实现餐饮业日销售情况分析仪&#xff0c;如下表&#xff1a; 认识分析仪&#xff1a; 切片器&#xff1a;店面 分为四部分&#xff1a;KPI 、组合图、饼图、数…

如何自学芯片设计?

众所周知&#xff0c;芯片设计自学还是比较困难的&#xff0c;更不存在速成的。这里简单说一下学习的规划。 学会相应的知识 无论是科班毕业&#xff0c;还是理工科专业&#xff0c;想要入行IC&#xff0c;那就一定要具备相关的基础知识。尤其是在学校里&#xff0c;学习的很…

Centos7 内核升级

一、背景 在 CentOS 使用过程中&#xff0c;高版本的应用环境可能需要更高版本的内核才能支持&#xff0c;所以难免需要升级内核&#xff0c;所以下面将介绍yum和rpm两种升级内核方式。 关于内核种类: kernel-ml——kernel-ml 中的ml是英文【 mainline stable 】的缩写&…

2W字正则表达式基础知识总结,这一篇就够了!!(含前端常用案例,建议收藏)

正则表达式 (Regular Expression&#xff0c;简称 RE 或 regexp ) 是一种文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a 到 z 之间的字母&#xff09;和特殊字符&#xff08;称为"元字符"&#xff09;正则表达式使用单个字符串来描述、匹配一系列匹…

wpscan常见的使用方法

目录 简单介绍 暴力破解 信息收集 指定用户爆破 命令集合 简单介绍 Wordpress是一个以PHP和MySQL为平台的免费自由开源的博客软件和内容管理系统。 WPScan是Kali Linux默认自带的一款漏洞扫描工具&#xff0c;它采用Ruby编写&#xff0c;能够扫描WordPress网站中的多种安…

微信微店怎么开店铺步骤【微信开店】

商家在微信平台主要是通过什么方式进行卖货呢&#xff0c;大家的答案都会是微信小店、小程序微店铺之类的&#xff0c;的确微信店铺是商家在微信平台上重要的卖货渠道&#xff0c;那么微信微店怎么开店铺&#xff0c;下面就给大家分享微信微店怎么开店铺步骤。 一、准备好资料…

Netty启动流程源码剖析

案例 本文利用natty-all-source 包下的的demo案例 echo来分析下源码&#xff0c;代码如下&#xff1a;server 端代码 /*** Echoes back any received data from a client.*/ public final class EchoServer {static final boolean SSL System.getProperty("ssl") …

day14_oop_抽象_接口

今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、作业 二、抽象 三、接口 零、 复习昨日 多态的好处: 扩展性强.加入新的功能,不需要改动代码降低代码耦合度(解耦合或者松耦合) 一、抽象类 1.1 抽象类…

C# VS2010 Winform 学习笔记遇见问题

参考书本《Visual C# .Net程序设计与应用开发》 学习C#&#xff1a; 对象的封装性&#xff1a;通过get()、set()函数读写。 1.Visual C#面向对象编程中的继承、多态。 2.enum&#xff1a;枚举&#xff0c;array.copy方法&#xff1a;数组拷贝&#xff0c;public static voi…

以应用为导向,看声纹识别中的音频伪造问题

声纹识别&#xff0c;又称说话人识别&#xff0c;是根据语音信号中的声纹特征来识别话者身份的过程&#xff0c;也是一种重要的生物认证手段。历经几十年的研究&#xff0c;当前声纹识别系统已取得了令人满意的性能表现&#xff0c;并在安防、司法、金融、家居等诸多领域中完成…

jenkins构建报错:.java:16: error: package javafx.util does not exist

1、报错 jenkins构建报错 package javafx.util does not exist2、报错原因 代码发现使用了javafx类&#xff0c;该类仅存在OracleJDK中&#xff0c;OpenJDK中没有该类。 jenkins服务器安装的是openjdk 3、卸载OpenJDK 具体不概述了 4、离线安装OracleJDK 1&#xff09;…

SPI规范的使用和简介

前言 SPI全称Service Provider Interface&#xff0c;是Java提供的一套用来被第三方实现或者扩展的API&#xff0c;它可以用来启用框架扩展和替换组件。 整体机制图如下&#xff1a; Java SPI 实际上是“基于接口的编程&#xff0b;策略模式&#xff0b;配置文件”组合实现的…

win11/10+opencv3.x/4.x配置 VS2019方法(简单使用,亲测)

首先下载 opencv&#xff0c;去官网下载百度》输入opencv&#xff0c;点击opencv|home&#xff0c;进入官网。点击 “Library”---->Release点击 对应版本下的 window版本&#xff0c;点击 --安装--extract---》设置路径。这个就是把库文件扩展到指定的路径下&#xff0c;扩…

Nacos集群+Nginx负载均衡

搭建Nacos集群 注意: 3个或3个以上Nacos节点才能构成集群。要求服务器内存分配最好大于6G以上&#xff08;如果不够则需修改nacos启动脚本中的默认内存配置&#xff09;根据nacos自带的mysql建库脚本建立对应数据库&#xff08;/conf/nacos-mysql.sql&#xff09;如果是三台服…

KNN&K-means从入门到实战

作者&#xff1a;王同学 来源&#xff1a;投稿 编辑&#xff1a;学姐 1. 基本概念 1.1 KNN k近邻法&#xff08;k-nearest neighbor&#xff0c;k-NN&#xff09;是一种基本分类与回归方法。 k近邻法的输入为实例的特征向量对应于特征空间的点&#xff1b;输出为实例的类别&…