重学SpringBoot3-SPI机制

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞👍收藏⭐评论✍

重学SpringBoot3-SPI机制

  • 什么是 SPI?
  • Spring Boot 中的 SPI 机制
    • spring.factories 文件
    • 自动配置的实现
    • 启动流程中的作用
  • SPI实际应用
    • 步骤 1: 新建模块
    • 步骤 2: 创建自动配置类
    • 步骤 3: 注册自动配置类
    • 步骤 4: 使用
    • 步骤 5: 测试
  • 最佳实践与注意事项
    • 1. 明确条件注解
    • 2. 避免类路径问题
    • 3. 使用 `@ConditionalOnMissingBean`
    • 4. 文档和示例
    • 5. 分离自动配置和业务逻辑
  • 总结

Spring Boot 的核心特性之一是其强大的自动配置功能,它极大地简化了 Spring 应用程序的配置。这种自动配置部分依赖于 Spring Boot 的服务提供者接口(SPI)机制,它允许开发者以模块化和可插拔的方式扩展和定制框架行为。接下来将详细探讨 Spring Boot 3 中的 SPI 机制,并通过示例展示如何实际使用它来实现。

什么是 SPI?

SPI(Service Provider Interface)即服务提供者接口,是一种服务发现机制,允许开发者和框架发现和加载可用的服务实现,而不需要在代码中硬编码具体的实现。这种机制使得软件系统能够更加灵活和可扩展。

在 Java 平台上,SPI 通常是通过 java.util.ServiceLoader 类实现的,但 Spring Boot 对这一概念进行了扩展,以支持其自动配置和模块化架构。

Spring Boot 中的 SPI 机制

Spring Boot 利用 spring.factories (注意:从 SpringBoot 2.7 起自动配置不推荐使用 /META-INF/spring.factories 文件,而是在/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports)文件,位于每个项目根目录的 META-INF/ 目录下,来实现其 SPI 机制。这个文件列出了与自动配置相关的接口及其实现类,Spring Boot 启动时会加载这些配置。

spring.factories 文件

这个文件使用键值对的格式列出了多种服务类型及其对应的实现类,常见的服务类型包括:

  • org.springframework.boot.autoconfigure.EnableAutoConfiguration:用于自动配置。
  • org.springframework.context.ApplicationListener:用于应用事件监听器。
  • org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider:用于模板引擎的可用性判断。

以下是 spring.factories 文件的一个典型例子:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.JpaAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfigurationorg.springframework.context.ApplicationListener=\
com.example.MyApplicationListener

Spring Boot 3 则要在 resources/META_INFO/spring/ 目录下新建 org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,并填入需要自动配置的类的全路径:

com.example.JpaAutoConfiguration

自动配置的实现

在 Spring Boot 中,自动配置类使用 @ConditionalXxx 注解来控制配置类的加载条件。这允许 Spring Boot 根据当前应用的环境,如类路径上的类、环境变量、系统属性等,条件性地应用配置,例如,一个自动配置类可能只在 JPA 实体类存在时才加载:

@Configuration
@ConditionalOnClass(name = "javax.persistence.Entity")
public class JpaAutoConfiguration {// 配置 JPA 相关的 beans
}

启动流程中的作用

在 Spring Boot 的启动流程中,当 SpringApplication 类被调用时,它将初始化一个 SpringApplicationContext。在这个过程中,Spring Boot 通过 SpringFactoriesLoader 类来加载 spring.factoriesorg.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中定义的各种组件,包括自动配置类。然后,根据应用的实际环境(比如类路径上的库和定义的 Beans),以及自动配置类上的条件注解,决定是否激活这些自动配置类。

SPI实际应用

让我们通过一个自定义 stater 示例来展示如何创建和使用自定义的自动配置。

步骤 1: 新建模块

自定义的 starter 不需要启动类,需要删掉。

步骤 2: 创建自动配置类

创建一个自动配置类,这个类将提供一个服务,仅在某个特定的类如 SpecificClass 存在于启动类类路径上时才加载 MyService 类型的 bean。

package com.coderjia.spi.config;import com.coderjia.spi.service.MyService;
import com.coderjia.spi.service.impl.MyServiceImpl;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author CoderJia* @create 2024/5/5 下午 03:29* @Description**/@Configuration
@ConditionalOnClass(name = "com.coderjia.features.config.SpecificClass")
public class MyAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic MyService MyService() {return new MyServiceImpl();}
}

MyService 类简单实现:

public class MyServiceImpl implements MyService {@Overridepublic void sayHello() {System.out.println("hello");}
}

步骤 3: 注册自动配置类

接下来,SpringBoot 2.7 以下在模块的 META-INF/spring.factories 文件中注册这个自动配置类:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.coderjia.spi.config.MyAutoConfiguration

SpringBoot 2.7 及以上在 /META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中添加自动配置类:

com.coderjia.spi.config.MyAutoConfiguration

这样配置后,只要 SpecificClass 类存在于类路径上,Spring Boot 就会自动配置 MyService

步骤 4: 使用

在其他项目中,只需 pom 文件中引入我们自定义的 starter 依赖,并确保 SpecificClass 类在类路径上,Spring Boot 将自动应用这个配置。

        <dependency><groupId>com.coderjia</groupId><artifactId>spring-boot3-07-spi</artifactId><version>0.0.1-SNAPSHOT</version></dependency>

步骤 5: 测试

首先,如果当前项目中启动类所在路径及其子路径不存在 SpecificClass 类,则从 IOC 容器中取不到 MyService

不存在SpecificClass类

当在当前项目中创建了 SpecificClass 类,则可以正常拿到 MyService bean:

存在SpecificClass类

最佳实践与注意事项

在利用 Spring Boot 的 SPI 机制开发自定义 starter 或自动配置时,有几个最佳实践和注意事项可以帮助确保项目的成功和维护性:

1. 明确条件注解

使用条件注解(如 @ConditionalOnClass@ConditionalOnBean)时,应尽量明确条件,确保你的自动配置仅在满足特定条件时才应用。这避免了配置冲突和非预期的行为,特别是在复杂的项目中。

2. 避免类路径问题

在设计自动配置时,注意类路径上可能出现的冲突。例如,如果自动配置依赖于某个库,确保这个库不会与项目中已有的库版本冲突。

3. 使用 @ConditionalOnMissingBean

在定义提供服务的 Bean 时,使用 @ConditionalOnMissingBean 注解可以确保在应用中已存在相同类型的 Bean 时,自动配置不会再创建新的 Bean,从而避免重复配置。

4. 文档和示例

为你的自定义 starter 或自动配置提供详细的文档和使用示例。这对于其他开发者来说是非常有价值的,特别是在解决依赖和配置问题时。

5. 分离自动配置和业务逻辑

将自动配置代码和业务逻辑代码分开,自动配置模块不应包含业务逻辑,它只应负责自动装配和条件判断。这样做可以提高模块的清晰度和重用性。

总结

Spring Boot 的 SPI 机制不仅强化了框架的自动配置能力,还提供了一种灵活且强大的方式来扩展和定制应用程序的行为。通过合理利用这一机制,开发者可以显著简化 Spring 应用的配置过程,加速开发和部署周期。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

瑞友天翼应用虚拟化系统SQL注入致远程代码执行漏洞复现

0x01 产品简介 瑞友天翼应用虚拟化系统是西安瑞友信息技术资讯有限公司研发的具有自主知识产权,基于服务器计算架构的应用虚拟化平台。它将用户各种应用软件集中部署在瑞友天翼服务器(群)上,客户端通过WEB即可快速安全的访问经服务器上授权的应用软件,实现集中应用、远程接…

AIGC技术带给我们什么?基于AIGC原理及其技术更迭的思考

AIGC技术带给我们什么&#xff1f;基于AIGC原理以及技术更迭的思考 前言 AI&#xff0c;这个词在如今人们的视野中出现频率几乎超过了所有一切其他的事物&#xff0c;更有意思的是&#xff0c;出现频率仅次于这个词的&#xff0c;几乎都会加上一个修饰亦或是前缀——AI&#…

Ansible --- playbook 脚本+inventory 主机清单

一 inventory 主机清单 Inventory支持对主机进行分组&#xff0c;每个组内可以定义多个主机&#xff0c;每个主机都可以定义在任何一个或 多个主机组内。 如果是名称类似的主机&#xff0c;可以使用列表的方式标识各个主机。vim /etc/ansible/hosts[webservers]192.168.10.1…

ROS机器人实用技术与常见问题解决

问题速查手册&#xff08;时实更新&#xff09;更加全面丰富的问题手册记录 1.机器人使用GPARTED挂载未分配空间 需要在图型界面下操作&#xff0c;建议使用no machine连接 安装gparted磁盘分区工具, sudo apt-get install gparted -y 启动软件 sudo gparted 点击磁盘/内存…

QGraphicsView实现简易地图10『自适应窗口大小』

前文链接&#xff1a;QGraphicsView实现简易地图9『层级缩放显示底图』 自适应窗口大小 当地图窗口放大或缩小的时候&#xff0c;需要地图能够动态覆盖整个视口。 1、动态演示效果 2、核心代码 注&#xff1a;WHMapView继承自MapViewvoid WHMapView::resize() {if (m_curLev…

Tmux工具使用案例

Tmux工具使用案例 连接linux一般使用ssh&#xff0c;当ssh会话中需要长时间执行命令时&#xff0c;为了避免命令不受ssh会话影响&#xff0c;除了可以将命令通过nohup <cmd> &等方法放到后台执行外&#xff0c;也可以利用Tmux这个工具解绑SSH会话与执行命令&#xff…

机器学习第二天(监督学习,无监督学习,强化学习,混合学习)

1.是什么 基于数据寻找规律从而建立关系&#xff0c;进行升级&#xff0c;如果是以前的固定算式那就是符号学习了 2.基本框架 3.监督学习和无监督式学习&#xff1a; 监督学习&#xff1a;根据正确结果进行数据的训练&#xff1b; 在监督式学习中&#xff0c;训练数据包括输…

Python做自动化测试必知必会思维导图

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

标准IO函数-将bmp图片修改为德国国旗样式

代码&#xff1a; #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <semaphore.h…

通过 Java 操作 redis -- String 基本命令

关于 redis String 类型的相关命令推荐看 Redis - String 字符串 要想通过 Java 操作 redis&#xff0c;首先要连接上 redis 服务器&#xff0c;推荐看通过 Java 操作 redis -- 连接 redis 本博客只介绍了一小部分常用的命令&#xff0c;其他的命令根据上面推荐的博客也能很简单…

选择器、pxcook软件、盒子模型

结构伪类选择器 定义&#xff1a;根据结构的元素关系来查找元素。 <title>Document</title><style>li:first-child{color:aqua ;}li:last-child{color: aqua;}li:nth-child(3){color: aqua;}</style> </head> <body><ul><li>…

雷军-2022.8小米创业思考-6-互联网七字诀之专注:有所为,有所不为;克制贪婪,少就是多;一次解决一个最迫切的需求

第六章 互联网七字诀 专注、极致、口碑、快&#xff0c;这就是我总结的互联网七字诀&#xff0c;也是我对互联网思维的高度概括。 专注 从商业角度看&#xff0c;专注就是要“把鸡蛋尽量放在一个篮子里”。这听起来似乎有些不合理&#xff0c;大家的第一反应可能是“风险会不会…