首页 > 其他分享 >SPI机制在JDK/Spring/SpringBoot的区别?

SPI机制在JDK/Spring/SpringBoot的区别?

时间:2024-11-28 15:47:56浏览次数:8  
标签:HelloSpi SpringBoot JDK Spring ServiceLoader SPI public 加载

SPI机制在JDK/Spring/SpringBoot的区别?


   概要

   SPI (Service Provider Interface) 是一种服务发现机制,它允许第三方提供者为核心库或主框架提供实现或扩展。这种设计允许核心库/框架在不修改自身代码的情况下,通过第三方实现来增强功能。

   一、JDK原生的SPI

   1.  定义和发现

  JDK的SPI主要通过在META-INF/services/目录下放置特定的文件来指定哪些类实现了给定的服务接口。这些文件的名称应为接口的全限定名,内容为实现该接口的全限定类名。

   2. 加载机制

   ServiceLoader类使用Java的类加载器机制从META-INF/services/目录下加载和实例化服务提供者。例如,ServiceLoader.load(MyServiceInterface.class)会返回一个实现了MyServiceInterface的实例迭代器。

   3. 应用示例

   在Java的生态系统中,SPI 是一个核心概念,允许开发者提供扩展和替代的实现,而核心库或应用不必更改,下面举出一个例子来说明。

   1)首先定义一个接口。

public interface HelloSpi {
    String getName();
    void handle();
}

   2)定义不同的实现类。

   全部代码和步骤如下:

   步骤1:定义一个服务接口,文件名: MessageService.java

public class OneHelloSpiImpl implements HelloSpi {
    @Override
    public String getName() {
        return "One";
    }
    @Override
    public void handle() {
        System.out.println(getName() + "执行");
    }
}
public class TwoHelloSpiImpl implements HelloSpi {
    @Override
    public String getName() {
        return "Two";
    }
    @Override
    public void handle() {
        System.out.println(getName() + "执行");
    }
}

   3)在指定目录(META-INF.services)下创建文件

   文件名是接口的全类名,文件内容是实现类的全类名。

   这里创建的文件名是 org.example.chapter15.HelloSpi , 里面的内容为:

org.example.chapter15.OneHelloSpiImpl
org.example.chapter15.TwoHelloSpiImpl

   4)测试

public class Test {
    public static void main(String[] args) {
        ServiceLoader<HelloSpi> load = ServiceLoader.load(HelloSpi.class);
        Iterator<HelloSpi> iterator = load.iterator();
        while (iterator.hasNext()) {
            HelloSpi next = iterator.next();
            System.out.println(next.getName() + " 准备执行");
            next.handle();
        }
        System.out.println("执行结束");

    }
}

// 执行结果
One 准备执行
One执行
Two 准备执行
Two执行
执行结束

   通过执行结果我们可以看出,HelloSpi接口的所有实现类都得到了调用,我们可以通过这种机制根据不同的业务场景实现拓展的效果。示例是通过ServiceLoader实现的,我们来看一下这个类。

   4. ServiceLoader

   ServiceLoader是一个简单的服务提供者加载工具。是JDK6引进的一个特性。

   部分源码如下:

public final class ServiceLoader<S>  implements Iterable<S>
{
    //指定服务提供者配置文件的基本路径
    private static final String PREFIX = "META-INF/services/"; 

    private final ClassLoader loader;

    //构造器
    private ServiceLoader(Class<S> svc, ClassLoader cl) {
        service = Objects.requireNonNull(svc, "Service interface cannot be null");

        //默认是系统类加载器(也叫做应用程序类加载器)
        loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
        acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
        reload();
    }

    public static <S> ServiceLoader<S> load(Class<S> service) {
        //获取当前线程的线程上下文类加载器
        ClassLoader cl = Thread.currentThread().getContextClassLoader();

        //调用下面的方法
        return ServiceLoader.load(service, cl);
    }
    //根据指定的服务接口(service)和类加载器(cl)加载服务提供者
    public static <S> ServiceLoader<S> load(Class<S> service,ClassLoader loader) 
    {
      return new ServiceLoader<>(service, loader);
    }
    //...
}

    load方法是通过获取当前线程的线程上下文类加载器实例来加载的。Java应用运行的初始线程的上下文类加载器默认是系统类加载器。这里其实破坏了双亲委派模型,因为Java应用收到类加载的请求时,按照双亲委派模型会向上请求父类加载器完成,这里并没有这么做 。

   5. 缺点

   JDK原生的SPI每次通过ServiceLoader加载时都会初始化一个新的实例,没有实现类的缓存,也没有考虑单例等高级功能。

   6. 应用场景

   Java中有许多我们常见的框架使用SPI机制的地方,JDBC,Dubbo,Logback等,Spring中也有使用。

   二、Spring的SPI

   Spring SPI对 Java SPI 进行了封装增强。我们只需要在 META-INF/spring.factories 中配置接口实现类名,即可通过服务发现机制,在运行时加载接口的实现类。

   Spring的SPI不仅仅是服务发现,它提供了一套完整的插件机制。Spring的核心框架提供了很多接口和抽象类,如BeanPostProcessor, PropertySource, ApplicationContextInitializer等,这些都可以看作是Spring的SPI。开发者可以实现这些接口来扩展Spring的功能。这些接口允许开发者在Spring容器的生命周期的不同阶段介入,实现自己的逻辑。

   1.  应用示例

   1)配置

   还是采用上面的接口定义与实现,配置放在 META-INF/spring.factories中

com.yp.service.HelloSpi=com.yp.service.impl.OneHelloSpiImpl,com.yp.service.impl.TwoHelloSpiImpl

   2) 测试

public class HelloSpiTest {
    @Test
    public void testSpringSpi() {
        List<HelloSpi> helloSpiList = SpringFactoriesLoader.loadFactories(HelloSpi.class, this.getClass().getClassLoader());
        Iterator<HelloSpi> iterator = helloSpiList.iterator();
        while (iterator.hasNext()) {
            HelloSpi next = iterator.next();
            System.out.println(next.getName() + " 准备执行");
            next.handle();
        }
        System.out.println("执行结束");
    }
}

//执行结果为
sql 代码解读复制代码One 准备执行
One执行
Two 准备执行
Two执行
执行结束

 

   

1. 与IoC集成
与JDK的SPI不同,Spring的SPI与其IoC (Inversion of Control) 容器集成,使得在SPI实现中可以利用Spring的全部功能,如依赖注入。

2. 条件匹配:Spring提供了基于条件的匹配机制,这允许在某些条件下只加载特定的SPI实现,例如,可以基于当前运行环境的不同来选择加载哪个数据库驱动。

3. 配置
Spring允许通过spring.factories文件在META-INF目录下进行配置,这与JDK的SPI很相似,但它提供了更多的功能和灵活性。


三、SpringBoot的SPI


Spring Boot有一个与SPI相似的机制,但它并不完全等同于Java的标准SPI。

Spring Boot的自动配置机制主要依赖于spring.factories文件。这个文件可以在多个jar中存在,并且Spring Boot会加载所有可见的spring.factories文件。我们可以在这个文件中声明一系列的自动配置类,这样当满足某些条件时,这些配置类会自动被Spring Boot应用。

1. spring.factories机制

spring.factories是Spring Boot的一个特性,允许开发者自定义自动配置。通过spring.factories文件,开发者可以定义自己的自动配置类,这些类在Spring Boot启动时会被自动加载。
在这种情况下,SpringFactoriesLoader的使用,尤其是通过spring.factories文件来加载和实例化定义的类,可以看作是一种特定的SPI实现方式,但它特定于Spring Boot

   参考链接:

   https://juejin.cn/post/7197070078361387069

标签:HelloSpi,SpringBoot,JDK,Spring,ServiceLoader,SPI,public,加载
From: https://www.cnblogs.com/hld123/p/18574388

相关文章

  • 基于SpringBoot+Vue的学生报名系统的设计与实现(源码+lw+部署+讲解)
    文章目录1.前言2.详细视频演示3.具体实现截图4.技术可行性分析5.技术简介5.1后端框架SpringBoot5.2前端框架Vue5.3系统开发平台6.系统架构设计7.程序操作流程8.业务流程设计9.为什么选择我们9.1自己的公众号9.2海量实战案例10.代码参考11.数据库参考12.源码及文档获取......
  • 基于SpringBoot+Vue的大学生校园线上招聘系统的设计与实现(源码+lw+部署+讲解)
    文章目录1.前言2.详细视频演示3.具体实现截图4.技术可行性分析5.技术简介5.1后端框架SpringBoot5.2前端框架Vue5.3系统开发平台6.系统架构设计7.程序操作流程8.业务流程设计9.为什么选择我们9.1自己的公众号9.2海量实战案例10.代码参考11.数据库参考12.源码及文档获取......
  • Springboot高校学籍档案管理p84mw(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表学生,班级信息,专业信息,学院信息,学生成绩,档案文件开题报告内容一、研究背景及意义随着高校规模的不断扩大和信息化建设的推进,学籍档案管理工作面临着越来越......
  • Springboot高校体育场馆管理系统i0wqc(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表用户,场馆信息,场馆预约,体育器材,器材购买,线上饮品,饮品购买,教练信息,教练预约,器材类型,饮品类型开题报告内容一、研究背景与意义随着高校体育场馆数量的增......
  • 基于SpringBoot+Vue的校外兼职教师考勤管理系统的设计与实现(源码+lw+部署+讲解)
    文章目录1.前言2.详细视频演示3.具体实现截图4.技术可行性分析5.技术简介5.1后端框架SpringBoot5.2前端框架Vue5.3系统开发平台6.系统架构设计7.程序操作流程8.业务流程设计9.为什么选择我们9.1自己的公众号9.2海量实战案例10.代码参考11.数据库参考12.源码及文档获取......
  • 基于SpringBoot+Vue的家具商城系统的设计与实现(源码+lw+部署+讲解)
    文章目录1.前言2.详细视频演示3.具体实现截图4.技术可行性分析5.技术简介5.1后端框架SpringBoot5.2前端框架Vue5.3系统开发平台6.系统架构设计7.程序操作流程8.业务流程设计9.为什么选择我们9.1自己的公众号9.2海量实战案例10.代码参考11.数据库参考12.源码及文档获取......
  • MJGA,让 Java 再次伟大,开箱即用 Spring Boot 怕不怕 Gin?
    来源:juejin.cn/post/7245942451105562685前言隔壁组的云计算零零后女同事,后文简称云女士,非说Go的Gin框架比Springboot更加的开箱即用,我心想在Java里面Springboot已经打遍天下无敌手,这份底蕴岂是Gin能比。但是云女士突出一个执拗,非我要PK一把,PK内容就是她使用......
  • 毕业设计 基于Springboot的宠物寄养管理系统
    源码获取欢迎留言一、摘要基于SpringBoot框架的宠物寄养管理系统,服务于员工、管理员和普通用户。员工模块提供寄养、接送、医疗等全方位管理功能,简化工作流程;管理员模块则涵盖数据、公告、服务等综合管理,确保系统稳定运行;用户模块则提供直观友好的寄养服务选择和个人信息......
  • SpringBoot框架在宠物领养系统中的应用
    摘要如今社会上各行各业,都在用属于自己专用的软件来进行工作,互联网发展到这个时候,人们已经发现离不开了互联网。互联网的发展,离不开一些新的技术,而新技术的产生往往是为了解决现有问题而产生的。针对于宠物领养信息管理方面的不规范,容错率低,管理人员处理数据费工费时,采用......
  • 宠物领养技术:SpringBoot框架应用
    摘要如今社会上各行各业,都在用属于自己专用的软件来进行工作,互联网发展到这个时候,人们已经发现离不开了互联网。互联网的发展,离不开一些新的技术,而新技术的产生往往是为了解决现有问题而产生的。针对于宠物领养信息管理方面的不规范,容错率低,管理人员处理数据费工费时,采用......