如何写自己的springboot starter?自动装配原理是什么?
如何写自己的springboot starter?自动装配原理是什么?
1. 不用starter有什么弊端?
- 我们开发需要引入maven依赖,如果我们需要的依赖又有它自身所需要的依赖。我们需要同时去引入才能去使用,这种模式让我们苦不堪。例如要在项目中使用 Spring Data JPA 进行数据库操作,需要手动添加 Spring Data JPA、Hibernate、数据库驱动等相关依赖,这不仅需要开发者了解每个依赖的具体信息,还容易出现版本不兼容的问题,因为不同版本的依赖之间可能存在冲突。
- 配置麻烦,在SSM时期,大量的配置让我们晕头转向,没有starter的自动配置功能,需要手动编写大量的配置类和配置文件来启用和配置各种功能。例如,配置 Spring Data JPA 时,需要手动配置数据源、实体管理器工厂、事务管理器等
- 如果另一个项目也需要同时去做同样的功能,如果不用starter只能使用CV大法把之前配置的都移过来,CV有可能出错,也让项目臃肿。
针对以上缺点,starter诞生它只需要引入一个依赖,搞定!
常见的starter例如:
spring-boot-starter
spring-boot-starter-web
spring-boot-starter-test
spring-cloud-starter-alibaba-nacos-discovery
druid-spring-boot-starter
2. springboot自动装配
要想自定义一个starter就要知道springboot是怎么样自动装配bean的
2.1 核心注解:
- @SpringBootApplication:这是一个组合注解,相当于同时使用了 @Configuration、@EnableAutoConfiguration 和 @ComponentScan 注解。它标记了主应用程序类,并告诉 Spring Boot 开始组件扫描、自动配置和装配。
- @EnableAutoConfiguration:该注解用于启用 Spring Boot 的自动配置功能。它会根据应用程序的依赖关系和当前环境,自动注册所需的 bean。
- @ComponentScan:该注解用于启用组件扫描,以便 Spring Boot 可以自动发现和注册标有 @Component、@Service、@Repository 和 @Controller 注解的类。
- @ConditionalOnClass 和 @ConditionalOnMissingClass:这两个条件化注解用于根据类路径上是否存在特定的类来决定是否注册 bean。@ConditionalOnClass 在类路径上存在指定类时生效,而 @ConditionalOnMissingClass 在类路径上不存在指定类时生效。
- @ConditionalOnBean 和 @ConditionalOnMissingBean:这两个条件化注解用于根据是否存在特定的 bean 来决定是否注册 bean。@ConditionalOnBean 在容器中存在指定的 bean 时生效,而 @ConditionalOnMissingBean 在容器中不存在指定的 bean 时生效。
- @ConditionalOnProperty:该条件化注解用于根据配置属性的值来决定是否注册 bean。它可以根据配置文件中的属性值来决定是否启用或禁用特定的 bean。
tips: 如果官方给你的注解不够满足需求可以自己创建一个Conditional,@Conditional(value = TestCondition.class)
public class TestCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return true;
}
}
2.2 自动装配大白话
- springboot启动类注解@SpringBootApplication是一个组合注解 里面包含了@EnableAutoConfiguration,即开启自动装配
- @Import(AutoConfigurationImportSelector.class),导入AutoConfigurationImportSelector,并通过 selectImports 方法读取 META-INF/spring.factories 文件中配置的全类名
tips: 从spring boot2.7开始,慢慢不支持META-INF/spring.factories文件了需要导入的自动配置类可以放在
/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports - 并按照@ConditionalOnClass这样条件过滤的注解,如果满足条件注入bean
3. starter前知
3.1 取名该怎么样取?
spring官方文档上是这样说的 https://docs.spring.io/spring-boot/docs/2.0.0.M5/reference/htmlsingle/#boot-features-custom-starter-naming
翻译:
请确保为启动器提供合适的名称空间。不要以spring-boot作为模块名的开头,即使您使用的是不同的Maven groupId。我们可能会在将来为您自动配置的东西提供官方支持。
这是一条经验法则。假设您正在为“acme”创建一个启动器,将自动配置模块命名为acme-spring-boot-autoconfigure,将启动器命名为acme-spring-boot-starter。如果只有一个模块结合了这两个模块,那么使用acme-spring-boot-starter。
此外,如果启动器提供了配置键,请为它们使用适当的名称空间。特别是,不要在Spring Boot使用的命名空间(例如server、management、Spring等)中包含键。这些都是“我们的”,我们可能会在将来改进/修改它们,这样可能会破坏你的东西。
确保触发元数据生成,以便也为您的键提供IDE帮助。您可能需要查看生成的元数据(META-INF/spring-configuration-metadata.json),以确保正确地记录了密钥。
一般来说取名 xxx-spring-boot-starter就可以了
3.2 starter项目目录介绍
- maven.spring-cloud-starter-alibaba-nacos-discovery
这个是有关于maven的文件 - additional-spring-configuration-metadata.json
{"properties": [
{
"name": "spring.cloud.loadbalancer.nacos.enabled",
"type": "java.lang.Boolean",
"defaultValue": false,
"description": "Integrate LoadBalancer or not."
}
]}
这个文件是配置元数据,很多时候我们可能会不知道这个starter有哪些是可以配置的,就可以来找这个文件,name就是属性名,defaultValue是默认值,description是描述。idea中配置文件里的补全提示也是读取这里的进行提示
- MANIFEST.MF
该文件包含了该 JAR 包的版本、创建人和类搜索路径等信息。 - spring.factories
spring.factories文件里的内容就是我们需要自启动装配的bean全路径
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
官方tips:不要让这些类被组件扫描到
还有一些另外可能出现的键
org.springframework.boot.autoconfigure.EnableAutoConfiguration:用于自动配置类
org.springframework.context.ApplicationContextInitializer:应用上下文初始化器org.springframework.context.ApplicationListener:应用事件监听器
org.springframework.boot.SpringApplicationRunListener:应用运行监听器
org.springframework.boot.env.PropertySourceLoader:属性源加载器
org.springframework.boot.diagnostics.FailureAnalyzer:失败分析器
org.springframework.boot.env.EnvironmentPostProcessor:环境后处理器
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter:自动配置导入过滤器
org.springframework.boot.autoconfigure.AutoConfigurationPackage:自动配置包
4. 实战需求来了
要实现一个starter,打印请求详细信息。
- 创建request-log-spring-boot-starter项目,打包方式为jar,引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope> <!-- 确保不重复引入 -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional> <!-- 生成配置元数据 -->
</dependency>
</dependencies>
- 创建RequestLogProperties类读取配置文件
@ConfigurationProperties(prefix = "request-log")
public class RequestLogProperties {
private boolean enabled = true; // 是否启用日志
private boolean logHeaders = true; // 是否记录请求头
private boolean logBody = false; // 是否记录请求体(默认关闭,可能影响性能)
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isLogHeaders() {
return logHeaders;
}
public void setLogHeaders(boolean logHeaders) {
this.logHeaders = logHeaders;
}
public boolean isLogBody() {
return logBody;
}
public void setLogBody(boolean logBody) {
this.logBody = logBody;
}
}
- resources下新建META-INF文件夹
- META-INF文件夹下新建spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.example.config.RequestLogAutoConfiguration
RequestLogAutoConfiguration类被spring.factories引入不需要@Configuration注解了
- 编写RequestLogAutoConfiguration类,加入条件判断
@ConditionalOnProperty(name = "request-log.enable", matchIfMissing = true)
@EnableConfigurationProperties(RequestLogProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
- 写RequestLoggingFilter类继承OncePerRequestFilter实现doFilterInternal进行业务逻辑
- 完工,测试
5. 代码提交到git上了:
https://gitee.com/isyuesen/request-log/tree/main/-
如何写自己的springboot starter?自动装配原理是什么?的更多相关文章
- 【springboot】自动装配原理
摘自:https://mp.weixin.qq.com/s/ZxY_AiJ1m3z1kH6juh2XHw 前言 Spring翻译为中文是"春天",的确,在某段时间内,它给Java开 ...
- SpringBoot启动流程分析(五):SpringBoot自动装配原理实现
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- springboot自动装配原理,写一个自己的start
springboot自动装配原理 第一次使用springboot的时候,都感觉很神奇.只要加入一个maven的依赖,写几行配置,就能注入redisTemple,rabbitmqTemple等对象. 这 ...
- springboot自动装配原理
最近开始学习spring源码,看各种文章的时候看到了springboot自动装配实现原理.用自己的话简单概括下. 首先打开一个基本的springboot项目,点进去@SpringBootApplica ...
- 深入理解SpringBoot之自动装配
SpringBoot的自动装配是拆箱即用的基础,也是微服务化的前提.其实它并不那么神秘,我在这之前已经写过最基本的实现了,大家可以参考这篇文章.这次主要的议题是,来看看它是怎么样实现的,我们透过源代码 ...
- 【Springboot】Springboot自动装配原理
1.核心注解就是 EnableAutoConfiguration 该注解会激活SpringBoot的自动装配功能: 代码如下: @Target(ElementType.TYPE) @Retentio ...
- SpringBoot | 2.1 SpringBoot自动装配原理
@ 目录 前言 1. 引入配置文件与配置绑定 @ImportResource @ConfigurationProperties 1.1 @ConfigurationProperties + @Enab ...
- SpringBoot自动装配原理解析
本文包含:SpringBoot的自动配置原理及如何自定义SpringBootStar等 我们知道,在使用SpringBoot的时候,我们只需要如下方式即可直接启动一个Web程序: @SpringBoo ...
- Spring Boot系列(二):Spring Boot自动装配原理解析
一.Spring Boot整合第三方组件(Redis为例) 1.加依赖 <!--redis--> <dependency> <groupId>org.springf ...
- Eureka 系列(03)Spring Cloud 自动装配原理
Eureka 系列(03)Spring Cloud 自动装配原理 [TOC] 0. Spring Cloud 系列目录 - Eureka 篇 本文主要是分析 Spring Cloud 是如何整合 Eu ...
随机推荐
- Qt编写安防视频监控系统60-子模块4云台控制
一.前言 云台控制是一个很老很基础的模块了,视频监控系统中必备的特殊模块之一,可以对选中的通道的摄像机(ONVIF协议),进行云台控制,可以控制球机的上下左右等各个方位的移动,还可以调节变倍步长,至于 ...
- OpenMMLab AI实战营 第五课笔记
OpenMMLab AI实战营 第五课笔记 目录 OpenMMLab AI实战营 第五课笔记 在气球数据集上训练检测模型 进入 mmdetection 主目录 下载并观察气球数据集 下载训练好的mas ...
- 2022 年数据科学研究综述:重点介绍 ML、DL、NLP 等
2022 年数据科学研究综述:重点介绍 ML.DL.NLP 等 当我们在 2022 年底临近时,我对许多著名研究小组完成的所有惊人工作感到振奋,他们将 AI.机器学习.深度学习和 NLP 的状态扩展到 ...
- 论文解读 原苏木素A通过靶向ACSL4/FTH1轴依赖性铁凋亡保护阿霉素诱导的心肌损伤和心功能障碍
同学们,大家好!今天给大家介绍一篇研究性论文,原苏木素A通过靶向ACSL4/FTH1轴依赖性铁凋亡保护阿霉素诱导的心肌损伤和心功能障碍,想了解这方面的同学们可以重点关注一下.这篇文章是2024年7月份 ...
- 记录下uniapp的请求封装
请求封装就是经常见的事但是从来没有记录过,今天来记录一下简单的封装 首先封装自己的域名,可以和封装写在一起,但是最好单独写一个独立的js文件 这边就以一个域名为例 let baseUrl='域名地址' ...
- Centos8 BAD错误
signature hdr data: BAD, no. of bytes(127884) out of range error: /var/cache/dnf/os-86dc4ac5eda5a39e ...
- Java实现任务管理器性能网络监控数据
在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率.内存占用.磁盘I/O以及网络流量等.对于开发者和系统管理员来说,了解这些性能数据有助于优化应用程序和 ...
- 【TCP协议】---协议详解
TCP协议 本文内容如下: 1)TCP协议概念 2)TCP头部结构和字段介绍 3)TCP流量控制 滑动窗口 4)TCP拥塞控制 ...
- FastReport实现遍历Dataset数据集计算
delphi在使用fastreport进行打印时,需要对数据进行计算求和. 在打印文本框的OnBeforePrint事件中进行以下代码即可实现效果 procedure Memo7OnBeforePri ...
- .NET最佳实践:webapi返回IAsyncEnumerable提升性能
什么是IAsyncEnumerable IAsyncEnumerable<T> 是 .NET 中用于表示异步数据流的接口. 它允许你逐个异步地获取数据项,而不是将所有数据一次性加载到内存中 ...