如何写自己的springboot starter?自动装配原理是什么?

官方文档地址:https://docs.spring.io/spring-boot/docs/2.6.13/reference/html/features.html#features.developing-auto-configuration

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 自动装配大白话

  1. springboot启动类注解@SpringBootApplication是一个组合注解 里面包含了@EnableAutoConfiguration,即开启自动装配
  2. @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
  3. 并按照@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,打印请求详细信息。

  1. 创建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>
  1. 创建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;
}
}
  1. resources下新建META-INF文件夹
  2. META-INF文件夹下新建spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.example.config.RequestLogAutoConfiguration

RequestLogAutoConfiguration类被spring.factories引入不需要@Configuration注解了

  1. 编写RequestLogAutoConfiguration类,加入条件判断
@ConditionalOnProperty(name = "request-log.enable", matchIfMissing = true)
@EnableConfigurationProperties(RequestLogProperties.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
  1. 写RequestLoggingFilter类继承OncePerRequestFilter实现doFilterInternal进行业务逻辑
  2. 完工,测试

5. 代码提交到git上了:

https://gitee.com/isyuesen/request-log/tree/main/-

如何写自己的springboot starter?自动装配原理是什么?的更多相关文章

  1. 【springboot】自动装配原理

    摘自:https://mp.weixin.qq.com/s/ZxY_AiJ1m3z1kH6juh2XHw 前言 Spring翻译为中文是"春天",的确,在某段时间内,它给Java开 ...

  2. SpringBoot启动流程分析(五):SpringBoot自动装配原理实现

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  3. springboot自动装配原理,写一个自己的start

    springboot自动装配原理 第一次使用springboot的时候,都感觉很神奇.只要加入一个maven的依赖,写几行配置,就能注入redisTemple,rabbitmqTemple等对象. 这 ...

  4. springboot自动装配原理

    最近开始学习spring源码,看各种文章的时候看到了springboot自动装配实现原理.用自己的话简单概括下. 首先打开一个基本的springboot项目,点进去@SpringBootApplica ...

  5. 深入理解SpringBoot之自动装配

    SpringBoot的自动装配是拆箱即用的基础,也是微服务化的前提.其实它并不那么神秘,我在这之前已经写过最基本的实现了,大家可以参考这篇文章.这次主要的议题是,来看看它是怎么样实现的,我们透过源代码 ...

  6. 【Springboot】Springboot自动装配原理

    1.核心注解就是 EnableAutoConfiguration  该注解会激活SpringBoot的自动装配功能: 代码如下: @Target(ElementType.TYPE) @Retentio ...

  7. SpringBoot | 2.1 SpringBoot自动装配原理

    @ 目录 前言 1. 引入配置文件与配置绑定 @ImportResource @ConfigurationProperties 1.1 @ConfigurationProperties + @Enab ...

  8. SpringBoot自动装配原理解析

    本文包含:SpringBoot的自动配置原理及如何自定义SpringBootStar等 我们知道,在使用SpringBoot的时候,我们只需要如下方式即可直接启动一个Web程序: @SpringBoo ...

  9. Spring Boot系列(二):Spring Boot自动装配原理解析

    一.Spring Boot整合第三方组件(Redis为例) 1.加依赖 <!--redis--> <dependency> <groupId>org.springf ...

  10. Eureka 系列(03)Spring Cloud 自动装配原理

    Eureka 系列(03)Spring Cloud 自动装配原理 [TOC] 0. Spring Cloud 系列目录 - Eureka 篇 本文主要是分析 Spring Cloud 是如何整合 Eu ...

随机推荐

  1. ElasticSearch接口

    DSL语法 DSL为ES过滤数据时的语法,可用于查询.删除等操作 基本构成 默认分页查询,size默认为10.ES查询默认最大文档数量限制为10000,可通过 index.max_result_win ...

  2. 快速定位Linux 内核驱动中GPIO冲突

    #全开开kernel log echo "8" > /proc/sys/kernel/printk #打开gpiolib 动态调试 echo 'file gpiolib.c ...

  3. Solution -「AGC 020F」Arcs on a Circle

    \(\mathscr{Description}\)   Link.   在一个周长为 \(c\) 的圆周上放置长度分别为 \(l_1,l_2,\cdots,l_n\) 的弧,每条弧的位置独立均匀随机. ...

  4. Solution -「LOJ #6895」Yet Another NPC Problem

    \(\mathscr{Description}\)   Link.   给定 \(l,m\),求当 \(k=m,m+1,\dots,m+l-1\) 时,所有 \(k\) 阶有标号简单无向图中,最大团大 ...

  5. Solution Set -「LOCAL」冲刺省选 Round XXVIII

    \(\mathscr{Summary}\)   A 题显然是图论模型嘛--但是卡得太久了,B 题 C 题都不好骗,裂开 qwq.   感觉时间安排上不尽合理,如果 B C 简单一点我这个就要挂打分了. ...

  6. MAUI APK安装到其他手机闪退问题

    在本地VS调试一切正常的,生成的APK安装到其他手机 发生闪退了 先是用abd连接 检查日志看: adb -s 192.168.1.10 logcat -v time > e:\log.txt ...

  7. MySQL 开启配置binlog以及通过binlog恢复数据

    -------------------------------------------------------------------------------------- # 查看binlog的列表 ...

  8. nginx配置参数优化

    ginx作为高性能web服务器,即使不特意调整配置参数也可以处理大量的并发请求.以下的配置参数是借鉴网上的一些调优参数,仅作为参考,不见得适于你的线上业务. worker进程 worker_proce ...

  9. jQuery详解

    目录 jQueryJS中创建对象jQuery选择器jQuery 操作 DOMjQuery 事件jQuery 动画JSON :Python工具 - pipPython工具 - VirtualEnvWEB ...

  10. ctfshow--web2 sql注入

    这题是考sql注入,我们先用个万能语句注入 发现它上面会出现 欢迎你,ctfshow 那么这就很明显了,这个用户的名字就是ctfshow 那么猜测flag会不会是在flag的用户里面呢我们提交一下 如 ...