SpringBoot3自动配置流程 SPI机制 核心注解 自定义starter

1. 自动配置流程

  1. 导入starter
  2. 依赖导入autoconfigure
  3. 寻找类路径下 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件
  4. 启动,加载所有 自动配置类 xxxAutoConfiguration
    1. 给容器中配置功能组件
    2. 组件参数绑定到 属性类中。xxxProperties
    3. 属性类配置文件前缀项绑定
    4. @Contional派生的条件注解进行判断是否组件生效

所有场景自动配置好可以直接使用,修改配置文件,就会修改底层参数,例如:通过修改yaml配置server.port,就可以修改tomcat运行端口,注入SpringBoot配置好的组件可以随时使用。

2. SPI机制

  • Java中的SPI(Service Provider Interface)是一种软件设计模式用于 在应用程序中动态地发现和加载组件 。SPI的思想是,定义一个接口或抽象类,然后通过在classpath中定义实现该接口的类来实现对组件的动态发现和加载。
    SPI的主要目的是解决在应用程序中使用 可插拔组件 的问题。例如,一个应用程序可能需要使用不同的日志框架或数据库连接池,但是这些组件的选择可能取决于运行时的条件。通过使用SPI,应用程序可以在运行时发现并加载适当的组件,而无需在代码中硬编码这些组件的实现类。
    在Java中,SPI的实现方式是通过在META-INF/services目录下创建一个以服务接口全限定名为名字的文件,文件中包含实现该服务接口的类的全限定名。当应用程序启动时,Java的SPI机制会自动扫描classpath中的这些文件,并根据文件中指定的类名来加载实现类。
    通过使用SPI,应用程序可以实现更灵活、可扩展的架构,同时也可以避免硬编码依赖关系和增加代码的可维护性。

在SpringBoot中,文件位置位于:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

场景:抽取聊天机器人场景,它可以打招呼.
效果:任何项目导入此starter都具有打招呼功能,并且问候语中的人名需要可以在配置文件中修改

  1. 创建自定义starter项目,引入spring-boot-starter基础依赖
  2. 编写模块功能,引入模块所有需要的依赖。
  3. 编写xxxAutoConfiguration自动配置类,帮其他项目导入这个模块需要的所有组件
  4. 编写配置文件META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports指定启动需要加载的自动配置
  5. 其他项目引入即可使用

3. @EnableXxxx 功能开关

自动配置,项目一启动,SPI文件中指定的所有类都会加载。通过@EnableXxxx手动控制哪些功能的开启; 手动导入。都是利用 @Import 把此功能要用的组件导入进去。

4. SpringBoot核心注解

1. @SpringBootApplication

@SpringBootConfiguration

就是: @Configuration ,容器中的组件,配置类。spring ioc启动就会加载创建这个类对象

@EnableAutoConfiguration:开启自动配置

开启自动配置

@AutoConfigurationPackage:扫描主程序包:加载自己的组件

  • 利用 @Import(AutoConfigurationPackages.Registrar.class) 想要给容器中导入组件。
  • 把主程序所在的包的所有组件导入进来。

@Import(AutoConfigurationImportSelector.class):加载所有自动配置类:加载starter导入的组件

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).getCandidates();Assert.notEmpty(configurations,"No auto configuration classes found in "+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "+ "are using a custom packaging, make sure that file is correct.");return configurations;}

扫描SPI文件:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@ComponentScan

组件扫描:排除一些组件(哪些不要)
排除前面已经扫描进来的配置类、和自动配置类。

@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

2. 完整启动加载流程

在这里插入图片描述

5. 自定义starter

1. 创建robot-boot-starter模块

这个模块作为公有的聊天机器人模块,也就是有很多项目模块都需要引入它

引入依赖

<parent><artifactId>spring-boot-starter-parent</artifactId><groupId>org.springframework.boot</groupId><version>3.0.5</version>
</parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.10</version><scope>provided</scope></dependency><!--        导入配置处理器,配置文件自定义的properties配置都会有提示--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency>
</dependencies>

自定义配置有提示。导入以下依赖重启项目,再写配置文件就有提示

@ConfigurationProperties(prefix = "robot", ignoreInvalidFields = true)  //此属性类和配置文件指定前缀绑定
@Component
@Data
public class RobotProperties {private String name;
}
<!--        导入配置处理器,配置文件自定义的properties配置都会有提示-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
</dependency>
@Service
public class RobotService {@Autowiredprivate RobotProperties robotProperties;public String hello(){return "你好," + robotProperties.getName();}
}

2. 创建spring-user模块

引入聊天机器人模块(robot-boot-starter)

<dependency><groupId>org.robot</groupId><artifactId>robot-boot-starter</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
@RequestMapping(value = "/user")
@RestController
public class UserController {//这个组件是在robot-boot-starter模块中定义的@Autowiredprivate RobotController robotController;public String robot(){return robotController.hello();}
}

yml配置

robot:name: chatgpt

6. 如何在业务模块中实现公有模块中的组件注册

方式一(指定包扫描)

Spring默认只扫描启动类目录下和子包下边的组件,所以这里要指定扫描robot-boot-starter

@ComponentScan(value = {"org.robot"}) //扫描机器人模块下的组件
@SpringBootApplication
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class, args);}
}

方式二(XxxAutoConfiguration)

robot-boot-starter模块写一个RobotAutoConfiguration,给容器中导入这个场景需要的所有组件

@Import({RobotController.class, RobotProperties.class, RobotService.class})
public class RobotAutoConfiguration {
}

spring-user模块中,导入RobotAutoConfiguration.class

@Import(RobotAutoConfiguration.class)
@SpringBootApplication
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class, args);}
}

方式三(@EnableXxx)

使用@EnableXxx机制,只要使用这个注解 就会开启这个功能

robot-boot-starter模块自定义@EnableRobot注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
//以上元注解直接找个@EnableXxx类 拷贝进来即可
@Import(RobotAutoConfiguration.class)
public @interface EnableRobot {}

spring-user模块中启用注解,相当于导入了RobotAutoConfiguration.class中导入的组件

@EnableRobot
@SpringBootApplication
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class, args);}
}

别人引入starter需要使用 @EnableRobot开启功能,灵活配置

方式四(完全自动配置)

  • 依赖SpringBoot的SPI机制
  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中编写好我们自动配置类的全类名即可
  • 项目启动,自动加载我们的自动配置类

robot-boot-starter类路径下新建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,里边放入指定要扫描的配置类

org.robot.config.RobotAutoConfiguration

这样只要别的项目引入了robot-boot-starter模块,里边的组件都会自动注入

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

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

相关文章

前端技术Vue学习笔记--001

前端技术Vue学习笔记 文章目录 前端技术Vue学习笔记1、Vue2和Vue3比较2、Vue简介3、Vue快速上手4、插值表达式{{}}5、Vue响应式特性6、Vue指令6.1、v-html指令6.2、v-show指令和v-if指令6.3、v-else指令和v-else-if指令6.4、v-on指令6.4.1、v-on指令基础6.4.2、v-on调用传参 6.…

Kubernetes_核心组件_kubelet_kubelet服务全解析(二)

文章目录 前言kubelet 架构kubelet 职责Node管理(节点管理)Pod管理 kubelet管理Podkubelet如何管理当前节点上所有Podkubelet三个端口kubelet获取Pod清单kubelet通过CRI接口管理Pod以及里面的容器 PodWorker的工作细节PodWorker的工作细节PLEG组件PLEG报错 kubelet创建并启动Po…

arcgis-利用等高线数据生成dem栅格

1、打开cass&#xff0c;展高程点&#xff0c;绘制三角网&#xff0c;绘制等高线&#xff0c;删除三角网和高程点。如下&#xff1a; 2、得到的等高线图&#xff0c;如下&#xff1a; 3、保存文件为dwg格式&#xff0c;随后打开arcmap软件&#xff0c;打开dwg的线层数据&#x…

网络安全防御篇之安全问题及防火墙简介

网络安全常识及术语 网络的脆弱性 什么样的网络是安全的

Java当中的深拷贝和浅拷贝

文章目录 一、前提二、浅拷贝1. BeanUtils实现浅拷贝 三、深拷贝1. 实现Cloneable接口并重写clone()方法&#xff1a;2. 使用序列化与反序列化&#xff1a; 一、前提 在计算机的内存中&#xff0c;每个对象都被赋予一个地址&#xff0c;该地址指向对象在内存中存储的位置。当我…

【MATLAB第59期】基于MATLAB的混沌退火粒子群CSAPSO-BP、SAPSO-BP、PSO-BP优化BP神经网络非线性函数拟合预测/回归预测对比

【MATLAB第59期】基于MATLAB的混沌退火粒子群CSAPSO-BP、SAPSO-BP、PSO-BP优化BP神经网络非线性函数拟合预测/回归预测对比 注意事项 不同版本matlab 不同电脑 加上数据集随机&#xff0c;BP权值阈值随机&#xff0c;进化算法种群随机&#xff0c;所以运行结果不一定和我运行…

集成了32位Cortex®M0内核XMC1302T038X0200AB、XMC1302Q040X0200AB 32MHz 200KB 闪存 工业MCU

XMC1000 32位工业 MCU 将 ARM Cortex™-M0 核心与领先的 65nm 制造工艺相结合&#xff0c;克服了目前 8 位设计的局限。XMC1000系列让目前的 8 位用户有机会享受 32 位的功耗&#xff0c;同时不在价格或易用性上做出妥协。XMC1000 在其细分市场提供最为广泛的闪存产品线&#x…

3分钟,快速上手Postman接口测试

Postman是一个用于调试HTTP请求的工具&#xff0c;它提供了友好的界面帮助分析、构造HTTP请求&#xff0c;并分析响应数据。实际工作中&#xff0c;开发和测试基本上都有使用Postman来进行接口调试工作。有一些其他流程的工具&#xff0c;也是模仿的Postman的风格进行接口测试工…

下载|GitLab 2023 年 DevSecOps 全球调研报告:安全左移深入人心、AI/ML 蔚然成风

目录 谁应该对应用程序安全负主要责任&#xff1f; 安全实践的最大挑战 AI 驱动研发&#xff0c;提升研发效率 各个角色使用的工具数量是多少&#xff1f; 一体化 DevSecOps 平台有哪些优势&#xff1f; 56%、74%、71%、65%、57% 这些数字和 DevSecOps 结合在一起&#xf…

android adb命令获取处于当前屏幕的Activity

android adb命令获取处于当前屏幕的Activity 使用adb命令&#xff1a; adb shell dumpsys activity activities 输出&#xff0c;例如: ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities) Display #0 (activities from top to bottom): * Task{38ef601 #5281 typ…

Java当中的栈

栈的理解 栈&#xff08;Stack&#xff09;是一种受限的线性数据结构&#xff0c;所谓受限是指栈只暴露栈顶和栈底的操作&#xff0c;其底层是由数组实现的。栈的特性是先进后出。 常用方法 注意上面的peek()方法和pop()方法的区别&#xff01; 实例 import java.util.Stack…

grpc中间件之链路追踪(otel+jaeger)

参考文档 https://github.com/grpc-ecosystem/go-grpc-middleware/blob/main/examples/client/main.go https://github.com/grpc-ecosystem/go-grpc-middleware/blob/main/examples/server/main.go https://github.com/open-telemetry/opentelemetry-go/blob/main/example/jaeg…

sql中group by 的使用

1、概述 Group By 从字面意义上理解就是根据By指定的规则对数据进行分组&#xff0c;所谓的分组就是将一个数据集划分为若干个小区域&#xff0c;然后针对若干个小区域进行数据处理 2、原始表 3、简单的Group By 示例1 select 类别&#xff0c;数量 as 数量之和 from A gro…

android studio 离线打包配置push模块

1.依赖引入 SDK\libs aps-release.aar, aps-unipush-release.aar, gtc.aar, gtsdk-3.2.11.0.aar, 从android studio的sdk中找到对应的包放到HBuilder-Integrate-AS\simpleDemo\libs下面 2.打开build.gradle&#xff0c;在defaultConfig添加manifestPlaceholders节点&#xff0c…

【代码随想录 | Leetcode | 第十天】哈希表 | 三数之和 | 四数之和

前言 欢迎来到小K的Leetcode|代码随想录|专题化专栏&#xff0c;今天将为大家带来哈希法~三数之和 | 四数之和的分享✨ 目录 前言15. 三数之和18. 四数之和总结 15. 三数之和 ✨题目链接点这里 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], num…

JVM运行时区域——对象创建内存分配过程

新创建的对象&#xff0c;都存放在伊甸园区域&#xff0c;当垃圾回收时&#xff0c;将伊甸园区域的垃圾数据销毁&#xff0c;然后将存活的对象转移到幸存者0区域&#xff0c;之后创建的新的对象还是存放在伊甸园区域&#xff0c;等到再次垃圾回收后&#xff0c;将伊甸园区域和幸…

HTML5——基础知识及使用

HTML 文件基本结构 <html><head><title>第一个页面</title></head><body>hello world</body> </html> html 标签是整个 html 文件的根标签(最顶层标签).head 标签中写页面的属性.body 标签中写的是页面上显示的内容.title 标…

Ansible自动化运维学习——综合练习

目录 (一)练习一 1.新建一个role——app 2.创建文件 3.删除之前安装的httpd服务和apache用户 4.准备tasks任务 (1)创建组group.yml (2)创建用户user.yml (3)安装程序yum.yml (4)修改模板httpd.conf.j2 (5)编写templ.yml (6)编写start.yml (7)编写copyfile.yml (8…

Python爬虫技术及其原理详解

概要 随着互联网的发展&#xff0c;大量的数据被存储在网络上&#xff0c;而我们需要从中获取有用的信息。Python作为一种功能强大且易于学习的编程语言&#xff0c;被广泛用于网络爬虫的开发。本文将详细介绍Python爬虫所需的技术及其原理&#xff0c;并提供相关的代码案例。 …

Mac电脑文件夹无权限问题

sudo cp 16.5.zip /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport 走到之前的folder &#xff0c;右键选择get info更改權限, 再應用到所有子文件夹 右下解鎖再加自己Read & Write, -右邊拉下應該可以應用到所有子文件 这样就可以…