以自定义线程池Starter为例,完整讲透SpringBoot自动装配底层全流程

发布时间:2026/7/20 18:56:21

以自定义线程池Starter为例,完整讲透SpringBoot自动装配底层全流程
先理清我们手写starter三个模块各自的作用这是自动装配的载体image我们一共写了三层工程各司其职缺一不可my-starter父工程只用来统一锁定SpringBoot版本、统一管理所有子模块版本本身不提供任何业务代码是Maven多模块的管理壳子threadpool-autoconfigure自动配置核心包这是自动装配真正干活的核心里面有三块关键代码ThreadPoolProperties绑定yml配置的属性类ThreadPoolAutoConfiguration线程池的自动配置类带条件注解负责创建线程池BeanMETA-INF/spring/xxx.imports 文件SPI注册文件告诉SpringBoot“我这里有一个自动配置类需要加载”threadpool-starter启动器空包里面一行Java代码都没有只在pom里依赖上面的autoconfigure包。它的作用就是给使用者提供一个统一依赖坐标别人只需要引入这个starter就能间接引入自动配置核心代码不用自己管理多个依赖。使用者会新建一个demo-test测试项目引入我们写好的starter写Controller注入线程池使用这是自动装配的使用者端。二、SpringBoot项目启动的第一阶段开启自动装配总开关我们demo-test的启动类上标注了SpringBootApplication这个注解是一个复合注解里面包含三个关键能力和自动装配强相关的是EnableAutoConfigurationComponentScan只会扫描当前demo-test项目自己包下的Controller、自定义配置类不会扫描第三方jar包里的代码这也是为什么我们不能把接口写在starter里Configuration标记当前启动类也是一个配置类EnableAutoConfiguration自动装配的总开关没有这个注解后面所有自动配置都不会执行。点开EnableAutoConfiguration源码它内部通过Import(AutoConfigurationImportSelector.class)导入了一个选择器类这个选择器就是自动装配底层的核心执行器整个自动装配的逻辑全部由这个类驱动。三、第二阶段选择器扫描所有jar找到我们线程池的自动配置类当程序走到AutoConfigurationImportSelector的核心方法getAutoConfigurationEntry()时会执行一套固定流程专门读取第三方jar里的自动配置程序遍历当前项目所有引入的依赖jar包包括我们导入的threadpool-starterstarter又传递依赖了autoconfigure包针对每一个jar包去固定路径读取文件SpringBoot3规范路径是META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports读到我们autoconfigure包里的这个文件文件里写了我们配置类的全类名com.starter.threadpool.autoconfigure.ThreadPoolAutoConfiguration程序会把这个类名存进一个待加载列表同理如果项目引入redis、web等官方starter也会读取对应imports文件收集所有官方自动配置类。简单说我们手写的imports文件就是给SpringBoot留的“路标”告诉启动程序我的jar包里有一个自动配置类记得加载它。如果不写这个文件SpringBoot完全不知道我们存在ThreadPoolAutoConfiguration自动装配直接失效。四、第三阶段根据条件注解判断我们的线程池配置类是否生效收集完所有自动配置类名后Spring不会直接全部加载会通过条件注解做过滤我们ThreadPoolAutoConfiguration上的注解就在这里生效首先判断类上ConditionalOnClass(ThreadPoolExecutor.class)校验当前JVM中是否存在ThreadPoolExecutor这个类这个类是JDK原生线程池类必然存在所以我们这个配置类不会被过滤保留下来举个对比如果是Redis自动配置会判断项目里有没有RedisTemplate类没引入redis starter就过滤掉配置实现按需装配确认配置类生效后处理EnableConfigurationProperties(ThreadPoolProperties.class)Spring会读取项目resources下的application.yml文件匹配前缀starter.threadpool的配置把yml里写的核心线程、最大线程、队列容量等数值自动注入到ThreadPoolProperties实体类中并且把这个属性类存入Spring容器后续创建线程池时直接读取配置参数此时ThreadPoolAutoConfiguration已经被Spring识别为标准Configuration配置类等待执行里面的Bean方法。五、第四阶段创建线程池Bean实现“自动装配”核心效果Spring处理配置类内部的Bean方法也就是我们创建ThreadPoolExecutor的方法这里ConditionalOnMissingBean注解发挥作用Spring先去当前容器中检索有没有已经存在ThreadPoolExecutor类型的Bean分两种情况情况1用户demo-test项目里没有手动写线程池Bean容器找不到对应Bean满足ConditionalOnMissingBean的条件执行我们的方法方法会拿着之前注入完成的ThreadPoolPropertiesyml配置参数new一个ThreadPoolExecutor线程池对象放入Spring单例容器情况2用户自己写了配置类手动创建了ThreadPoolExecutor Bean容器中已经存在对应实例注解生效跳过我们自动创建Bean的逻辑优先使用用户自定义的线程池满足扩展、覆盖的需求执行完成后Spring容器里已经存在一个可用的线程池实例不需要用户手动new、手动写配置类这就是“自动装配”带来的便捷。六、第五阶段使用者注入使用走完完整链路当Spring容器初始化完成后我们在demo-test的PoolTestController中写Resource private ThreadPoolExecutor threadPoolExecutorSpring会从容器中取出我们自动装配好的线程池Bean直接注入给Controller接口访问时就能调用线程池执行任务全程不需要用户关心线程池是怎么创建、怎么读取yml配置的。七、整条底层流程串联总结简化完整版开发者在测试项目引入自定义线程池starter启动类SpringBootApplication携带EnableAutoConfiguration开启自动装配底层AutoConfigurationImportSelector扫描所有jar包读取autoconfigure中的imports文件拿到线程池自动配置类的完整类名校验配置类上ConditionalOnClass确认配置类可以生效通过EnableConfigurationProperties读取application.yml的自定义线程池配置封装到属性类执行配置类里的Bean方法通过ConditionalOnMissingBean判断无自定义Bean则自动创建线程池放入Spring容器业务Controller直接注入容器中自动生成的线程池完成使用。补充设计思想为什么要这么设计这套自动装配解决了原生Spring的痛点原生Spring想要使用线程池必须自己写配置类、手动读取配置文件、手动注册Bean而通过starter自动装配把通用组件的创建逻辑、配置绑定逻辑全部封装到第三方jar使用者只需要引入依赖、简单写yml参数底层全部由SpringBoot自动完成同时依靠条件注解实现按需加载、支持用户自定义覆盖符合开闭原则。口述版SpringBoot项目启动类标注SpringBootApplication它是组合注解其中EnableAutoConfiguration注解内部带有Import导入自动配置选择器AutoConfigurationImportSelector这个选择器的selectImports方法会扫描项目所有导入的jar包读取每个jar包下META-INF/spring目录的AutoConfiguration.imports文件文件内记录所有候选自动配置类的全类名读取后存入候选列表。随后根据每个自动配置类上的Conditional系列注解做过滤仅满足条件的配置类会保留不满足条件直接丢弃。过滤后保留的自动配置类一般标注EnableConfigurationProperties(XXX.class)属性类XXX.class带有ConfigurationProperties(prefix “xxx”)注解Spring会读取application.yml中对应前缀的配置封装到该属性类并将属性类存入容器供自动配置类读取配置参数。

相关新闻

Arcade游戏开发:掌握Python 2D游戏的输入系统架构与实践

Arcade游戏开发:掌握Python 2D游戏的输入系统架构与实践

2026/7/20 18:46:20

Arcade游戏开发:掌握Python 2D游戏的输入系统架构与实践 【免费下载链接】arcade Easy to use Python library for creating 2D arcade games. 项目地址: https://gitcode.com/gh_mirrors/ar/arcade 在Python游戏开发领域,Arcade库以其简洁的API和…

7·15情感AI风控补全:拟人Agent Prompt注入越狱攻防全链路工程落地方案

7·15情感AI风控补全:拟人Agent Prompt注入越狱攻防全链路工程落地方案

2026/7/20 18:46:20

文章总目录715情感AI风控补全:拟人Agent Prompt注入越狱攻防全链路工程落地方案一、情感AI场景专属的三类Prompt注入攻击1. 人设劫持类注入2. 规则绕过隐喻注入3. 分层风控熔断劫持二、传统检测方案的三大工程缺陷三、五层风控架构新增:对抗注入识别分流…

从源码到部署:mlx-community/Qwopus3.6-27B-Coder-8bit模型转换全流程详解

从源码到部署:mlx-community/Qwopus3.6-27B-Coder-8bit模型转换全流程详解

2026/7/20 18:46:20

从源码到部署:mlx-community/Qwopus3.6-27B-Coder-8bit模型转换全流程详解 【免费下载链接】Qwopus3.6-27B-Coder-8bit 项目地址: https://ai.gitcode.com/hf_mirrors/mlx-community/Qwopus3.6-27B-Coder-8bit mlx-community/Qwopus3.6-27B-Coder-8bit是一款…

嵌入式功耗优化核心:深入解析TI PRCM模块的架构、寄存器与实战

嵌入式功耗优化核心:深入解析TI PRCM模块的架构、寄存器与实战

2026/7/21 10:37:20

1. 从手册到实践:为什么嵌入式开发者必须啃透PRCM在嵌入式系统开发这条路上,我见过太多工程师,尤其是刚入行的朋友,对“功耗优化”的理解还停留在“降低主频”或“进入休眠模式”的层面。他们往往更关注应用逻辑、算法实现&#x…

C++客户端---String类型

C++客户端---String类型

2026/7/21 10:37:20

SET/GET#include<iostream> #include<vector> #include<string> #include<unordered_map> #include<sw/redis.h> #include<chrono> #include<thread> void test(sw::redis::Redis& redis) {//引入命名空间using namespace std::…

Claude Code与OpenAI Codex协同实现高效代码审查

Claude Code与OpenAI Codex协同实现高效代码审查

2026/7/21 10:37:20

1. 项目概述&#xff1a;Claude Code与OpenAI Codex的协同工作流在代码开发领域&#xff0c;审查环节往往占据30%以上的开发时间。传统人工审查存在效率瓶颈&#xff0c;而AI辅助工具的出现正在改变这一现状。最近在开发者社区引起热议的Claude Code插件&#xff0c;通过桥接Op…

Claude Code内置浏览器:提升开发效率的集成开发环境新特性

Claude Code内置浏览器:提升开发效率的集成开发环境新特性

2026/7/21 10:37:20

1. Claude Code 内置浏览器到底解决了什么实际问题Claude Code 这次更新的内置浏览器功能&#xff0c;最直接的价值是让开发者在同一个工具里完成代码编写、文档查阅和问题排查&#xff0c;不用再反复切换窗口。很多人可能觉得这只是个便利性改进&#xff0c;但实际用起来会发现…

makedown

makedown

2026/7/21 10:37:20

markdown的后缀是.md 标题: 标题一## 标题一 标题 这是一段引用 把大象个放进冰箱 (有序列表) 打开冰箱把大象放进冰箱关上冰箱 无序列表(不排序) asdfghjjhgfdsawwwwww 任务列表(可以打对号) 吃饭 睡觉 呼吸 #include<iostream> int main(){return 0; }(用三个)数…

Spring Boot WebSocket 来单提醒怎么给外网验收?用 cpolar 临时公网地址跑通手机测试

Spring Boot WebSocket 来单提醒怎么给外网验收?用 cpolar 临时公网地址跑通手机测试

2026/7/21 10:27:19

Spring Boot WebSocket 来单提醒怎么给外网验收&#xff1f;用 cpolar 临时公网地址跑通手机测试来单提醒这类功能&#xff0c;最怕只在开发电脑上“看起来正常”。电脑浏览器能收到消息&#xff0c;不代表手机能响&#xff1b;本地 localhost 能连上&#xff0c;也不代表外网同…

微服务进阶:服务网格与Istio

微服务进阶:服务网格与Istio

2026/7/21 5:45:57

541|微服务进阶:服务网格与Istio 上篇文章我们聊了微服务的基本概念和拆分方法。 但微服务多了,问题也多了: 服务之间怎么通信? 怎么监控每个服务的调用链路? 熔断、限流、重试怎么做? 安全认证怎么统一? 以前这些都靠SDK库(比如Hystrix、Feign),每个服务都要集成…

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

零售超级终端全域协同:ShareKit 碰一碰商品流转业务落地案例

2026/7/21 9:56:14

一、零售门店全域协同业务背景与行业痛点 1.1 门店超级终端设备矩阵&#xff08;连锁便利店/商超标准配置&#xff09; 自助收银Kiosk一体机&#xff1a;顾客结算、自助核销优惠券、商品素材预览&#xff1b;运营折叠平板&#xff1a;店长后台商品上新、图片录入、活动配置、…

噗叽短视频界面分析

噗叽短视频界面分析

2026/7/21 3:09:32

1 和小红书类似&#xff0c;可以采用类似判断方法------------其实他比小红书好判断&#xff0c;因为他没有图片&#xff0c;控件位置几乎是固定的&#xff0c;都不用判断------------2 因为他没有点赞按钮------------而且几乎所有控件位置都是完全一样的&#xff0c;所以我就…

GraphRAG Local + Ollama:微软知识图谱本地化

GraphRAG Local + Ollama:微软知识图谱本地化

2026/7/21 0:06:35

普通 RAG 有个老毛病&#xff1a;你问它「这堆文档整体在讲什么」&#xff0c;它答不上来。因为它只会把问题切成向量&#xff0c;去几十个文本块里捞最相似的几段拼给模型看。可「整体讲什么」这种问题&#xff0c;答案根本不在任何单独一段里——它散在全篇的联系里。 微软的…

AI 数据产品化思考:让分析能力变成可售卖的数据服务

AI 数据产品化思考:让分析能力变成可售卖的数据服务

2026/7/21 0:06:35

AI 数据产品化思考&#xff1a;让分析能力变成可售卖的数据服务 大家好&#xff0c;我是朱大喜。这周一直在复盘具体的项目和技术&#xff0c;最后一篇聊点不一样的东西——数据产品化。做了这么多年数据分析&#xff0c;我发现一个规律&#xff1a;能卖出去的从来不是"分…

基于人机协作的 AI 研发新体系架构:从 Harness 工程到 Loop 工程实践

基于人机协作的 AI 研发新体系架构:从 Harness 工程到 Loop 工程实践

2026/7/21 0:06:35

本文完整呈现了企业级 AI Coding 落地的核心方法论&#xff1a;从 Harness 工程的微观/宏观定义&#xff0c;到 Loop 工程的六大构建模块&#xff0c;再到基于 SDD&#xff08;规范驱动开发&#xff09;的工程化落地路径。干货较多&#xff0c;建议收藏细读。 我从 22 年开始就…