当前位置: 首页 > news >正文

springboot启动流程 (3) 自动装配

在SpringBoot中,EnableAutoConfiguration注解用于开启自动装配功能。

本文将详细分析该注解的工作流程。

EnableAutoConfiguration注解

启用SpringBoot自动装配功能,尝试猜测和配置可能需要的组件Bean。

自动装配类通常是根据类路径和定义的Bean来应用的。例如,如果类路径上有tomcat-embedded.jar,那么可能需要一个TomcatServletWebServerFactory(除非已经定义了自己的Servlet WebServerFactory Bean)。

自动装配试图尽可能地智能化,并将随着开发者定义自己的配置而取消自动装配相冲突的配置。开发者可以使用exclude()排除不想使用的配置,也可以通过spring.autoconfig.exclude属性排除这些配置。自动装配总是在用户定义的Bean注册之后应用。

用@EnableAutoConfiguration注解标注的类所在包具有特定的意义,通常用作默认扫描的包。通常建议将@EnableAutoConfiguration(如果没有使用@SpringBootApplication注解)放在根包中,以便可以搜索所有子包和类。

自动装配类是普通的Spring @Configuration类,使用SpringFactoriesLoader机制定位。通常使用@Conditional方式装配,最常用的是@ConditionalOnClass和@ConditionalOnMissingBean注解。

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {/*** Exclude specific auto-configuration classes such that they will never be applied.*/Class<?>[] exclude() default {};/*** Exclude specific auto-configuration class names such that they will never be* applied.* 当类路径下没有指定的类时,可以使用这个属性指定排除的类*/String[] excludeName() default {};
}

该注解Import了AutoConfigurationImportSelector类,AutoConfigurationImportSelector类实现了DeferredImportSelector接口。

Import注解和DeferredImportSelector接口在之前的"Spring @Import注解源码分析"中详细分析过,此处在介绍它们,只分析AutoConfigurationImportSelector的工作流程。

AutoConfigurationImportSelector类

DeferredImportSelector接口

A variation of ImportSelector that runs after all @Configuration beans have been processed. This type of selector can be particularly useful when the selected imports are @Conditional.

Implementations can also extend the org.springframework.core.Ordered interface or use the org.springframework.core.annotation.Order annotation to indicate a precedence against other DeferredImportSelectors.

Implementations may also provide an import group which can provide additional sorting and filtering logic across different selectors.

AutoConfigurationGroup类

AutoConfigurationImportSelector的getImportGroup方法返回了AutoConfigurationGroup类。

private static class AutoConfigurationGroup implements DeferredImportSelector.Group, BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware {private final Map<String, AnnotationMetadata> entries = new LinkedHashMap<>();private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>();// ... 略@Overridepublic void process(AnnotationMetadata annotationMetadata,DeferredImportSelector deferredImportSelector) {// AutoConfigurationEntry类使用List保存Configuration类AutoConfigurationEntry autoConfigurationEntry =((AutoConfigurationImportSelector) deferredImportSelector).getAutoConfigurationEntry(annotationMetadata);this.autoConfigurationEntries.add(autoConfigurationEntry);for (String importClassName : autoConfigurationEntry.getConfigurations()) {this.entries.putIfAbsent(importClassName, annotationMetadata);}}@Overridepublic Iterable<Entry> selectImports() {// 查找排除的配置类Set<String> allExclusions = this.autoConfigurationEntries.stream().map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());// 所有配置类Set<String> processedConfigurations = this.autoConfigurationEntries.stream().map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream).collect(Collectors.toCollection(LinkedHashSet::new));// 将排除的配置类移除掉processedConfigurations.removeAll(allExclusions);// 排序return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream().map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName)).collect(Collectors.toList());}// ... 略
}

从上面的代码可以看出,查找自动装配类的逻辑在getAutoConfigurationEntry方法中。

getAutoConfigurationEntry方法

从META-INF/spring.factories文件解析EnableAutoConfiguration配置。

META-INF/spring.factories文件示例:

在这里插入图片描述

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {AnnotationAttributes attributes = getAttributes(annotationMetadata);// 查找自动装配类List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);// 以下几行为查找排除类、过滤等操作configurations = removeDuplicates(configurations);Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);// 这里的Filter是从META-INF/spring.factories文件解析出来的configurations = getConfigurationClassFilter().filter(configurations);// 触发事件fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions);
}protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {// 从META-INF/spring.factories文件查找EnableAutoConfiguration配置List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());return configurations;
}

SpringFactoriesLoader类loadFactoryNames方法

Load the fully qualified class names of factory implementations of the given type from “META-INF/spring.factories”, using the given class loader.

public static List<String> loadFactoryNames(Class<?> factoryType, ClassLoader classLoader) {String factoryTypeName = factoryType.getName();return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {MultiValueMap<String, String> result = cache.get(classLoader);if (result != null) {return result;}try {// FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"// 从类路径下查找META-INF/spring.factories文件Enumeration<URL> urls = (classLoader != null ?classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result = new LinkedMultiValueMap<>();while (urls.hasMoreElements()) {URL url = urls.nextElement();UrlResource resource = new UrlResource(url);// 获取properties配置Properties properties = PropertiesLoaderUtils.loadProperties(resource);for (Map.Entry<?, ?> entry : properties.entrySet()) {String factoryTypeName = ((String) entry.getKey()).trim();for (String factoryImplementationName :StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {result.add(factoryTypeName, factoryImplementationName.trim());}}}// 把配置添加缓存cache.put(classLoader, result);return result;} catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);}
}

相关文章:

springboot启动流程 (3) 自动装配

在SpringBoot中&#xff0c;EnableAutoConfiguration注解用于开启自动装配功能。 本文将详细分析该注解的工作流程。 EnableAutoConfiguration注解 启用SpringBoot自动装配功能&#xff0c;尝试猜测和配置可能需要的组件Bean。 自动装配类通常是根据类路径和定义的Bean来应…...

ansible-roles模块

roles用于层次性&#xff0c;结构化地组织playbook&#xff0c;roles能够根据层次型结构自动装载变量文件&#xff0c;tasks以及handlers等。要使用只要载playbook中使用include指令引入即可。 &#xff08;roles就是通过分别将变量&#xff0c;文件&#xff0c;任务&#xff…...

聊聊我做 NeRF-3D重建性能优化经历

我们新推出大淘宝技术年度特刊《长期主义&#xff0c;往往从一些小事开始——工程师成长总结专题》&#xff0c;专题收录多位工程师真诚的心路历程与经验思考&#xff0c;覆盖终端、服务端、数据算法、技术质量等7大技术领域&#xff0c;欢迎一起沟通交流。 本文为此系列第四篇…...

未磁科技全球首台64通道无液氦心磁图仪及首个培训基地落户北京安贞医院

【全球首台64通道无液氦心磁图仪在北京安贞医院举行开机仪式】 近日&#xff0c;在北京安贞医院举行了未磁科技全球首台64通道无液氦心磁图仪开机仪式&#xff0c;中国医学装备协会赵自林理事长、北京安贞医院纪智礼书记、张宏家院长、宋现涛教授&#xff0c;以及未磁科技蔡宾…...

SpringBoot 如何使用 ApplicationEventPublisher 发布事件

SpringBoot 如何使用 ApplicationEventPublisher 发布事件 在 SpringBoot 应用程序中&#xff0c;我们可以使用 ApplicationEventPublisher 接口来发布事件。事件可以是任何对象&#xff0c;当该对象被发布时&#xff0c;所有监听该事件的监听器都会收到通知。 下面是一个简单…...

【深度学习】2-3 神经网络-输出层设计

前馈神经网络(Feedforward Neural Network)&#xff0c;之前介绍的单层感知机、多层感知机等都属于前馈神经网络&#xff0c;它之所以称为前馈(Feedforward)&#xff0c;或许与其信息往前流有关&#xff1a;数据从输入开始&#xff0c;流过中间计算过程&#xff0c;最后达到输出…...

Python网络爬虫开发:使用PyQt5和WebKit构建可定制的爬虫

部分数据来源:ChatGPT 引言 在网络爬虫开发中,使用Web浏览器模拟用户行为是非常重要的。而在这个过程中,基于 WebKit 的框架可以提供比其他技术更紧密的浏览器集成,以及更高效、更多样化的页面交互方式。 在本文中,我们将通过一个使用基于 WebKit 的爬虫示例,并与类似…...

Laya3.0游戏框架搭建流程(随时更新)

近两年AI绘图技术有了长足发展&#xff0c;准备把以前玩过的游戏类型重制下&#xff0c;也算是圆了一个情怀梦。 鉴于unity商用水印和启动时间的原因&#xff0c;我决定使用Laya来开发。目前laya已经更新到了3.0以上版本&#xff0c;就用目前比较新的版本。 之后关于开发中遇到…...

.net 软件开发模式——三层架构

三层架构是一种常用的软件开发架构模式&#xff0c;它将应用程序分为三个层次&#xff1a;表示层、业务逻辑层和数据访问层。每一层都有明确的职责和功能&#xff0c;分别负责用户交互、业务处理和数据存储等任务。这种架构模式的优点包括易于维护和扩展、更好的组织结构和代码…...

SpringBoot如何优雅的实现重试功能

文章目录 使用背景spring-retry介绍快速使用加入依赖开启Retry使用参数 使用背景 在有些特定场景&#xff0c;如和第三方对接。 我们调用接口时需要支持重试功能&#xff0c;第一次调用没成功&#xff0c;我们需要等待x秒后再次调用。 通常会设置重试次数&#xff0c;避免业务…...

【CEEMDAN-VMD-GRU】完备集合经验模态分解-变分模态分解-门控循环单元预测研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

OpenText Exceed TurboX(ETX)—— 适用于 UNIX、Linux 和 Windows 的远程桌面解决方案

由于新技术的采用&#xff0c;以及商业全球化和全球协作的现实&#xff0c;几乎所有企业&#xff08;无论其规模和所处行业&#xff09;的员工的工作方式、时间和地点都发生了重大变化。业务领导者正在推动其 IT 部门提出解决方案&#xff0c;以帮助其远程员工提高工作效率&…...

【人工智能】— 逻辑回归分类、对数几率、决策边界、似然估计、梯度下降

【人工智能】— 逻辑回归分类、对数几率、决策边界、似然估计、梯度下降 逻辑回归分类Logistic Regression ClassificationLogistic Regression: Log OddsLogistic Regression: Decision BoundaryLikelihood under the Logistic ModelTraining the Logistic ModelGradient Desc…...

k8s pod “cpu和内存“ 资源限制

转载用于收藏学习&#xff1a;原文 文章目录 Pod资源限制requests&#xff1a;limits&#xff1a;docker run命令和 CPU 限制相关的所有选项如下&#xff1a; Pod资源限制 为了保证充分利用集群资源&#xff0c;且确保重要容器在运行周期内能够分配到足够的资源稳定运行&#x…...

datagrip 连接 phoenix

jar替换完后尽量重启datagrip. 然后重新连接即可. 不重启貌似报错... 效果:...

黑客入侵的常法

1.无论什么站&#xff0c;无论什么语言&#xff0c;我要渗透&#xff0c;第一件事就是扫目录&#xff0c;最好一下扫出个上传点&#xff0c;直接上传 shell &#xff0c;诸位不要笑&#xff0c;有时候你花很久搞一个站&#xff0c;最后发现有个现成的上传点&#xff0c;而且很容…...

VB报警管理系统设计(源代码+系统)

可定时显示报警系统是一个能够定时并及时报警,提醒人们安全有效地按计划完成任务的系统。本论文从软件工程的角度,对可定时显示报警系统做了全面的需求分析,简要说明了该系统的构思、特点及开发环境;阐述了系统的主要功能,论述了它的设计与实现,并且叙述了系统的测试与评…...

Redis入门 - Redis Stream

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis入门 - Redis Stream | CoderMast编程桅杆Redis入门 - Redis Stream Redis Stream 是 Redis 5.0 版本新增加的数据结构。 Redis Stream 主要用于消息队列&#xff08;MQ&#xff0c;Message Queue&#xff09;&#xf…...

微服务中常见问题

Spring Cloud 组件 Spring Cloud五大组件有哪些&#xff1f; Eureka&#xff1a;注册中心 Ribbon&#xff1a;负载均衡 Feign&#xff1a;远程调用 Hystrix&#xff1a;服务熔断 Zuul/Gateway&#xff1a;服务网关 随着SpringCloud Alibaba在国内兴起&#xff0c;我们项目中…...

更新删除清理购物车

目录 1 更新购物车 2 取会员门店购物车项 3 取会员门店购物车项(无缓存) 4 删除门店购物车某项 5 删除门店购物车多项 6 清理门店购物车 7 清理门店购物车 8 添加商品至购物车 9 添加商品至购物车...

AI的“血管”:从大模型需求看6G、高速光纤与智算中心网络的技术变革

大模型训练与推理的爆发&#xff0c;正以前所未有的力度重塑通信网络基础设施。6G、高速光纤、智算中心网络&#xff0c;正成为AI基础设施的“血管”&#xff0c;承载着算力的血液&#xff0c;决定智能的极限。当GPT-5.4的推理能力逼近人类专家&#xff0c;当Sora可以生成一分钟…...

基于springboot的中医院问诊知识科普系统的设计与实现-vue

目录系统架构设计前端技术选型模块划分关键技术实现开发阶段规划部署方案项目技术支持源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作系统架构设计 采用前后端分离架构&#xff0c;前端使用Vue.js框架&#xff0c;后端基于SpringBoot构建R…...

从零上手Neo4j Desktop:CSV数据导入与核心Cypher操作指南

1. Neo4j Desktop环境准备与数据导入 第一次打开Neo4j Desktop时可能会被它的界面搞得有点懵&#xff0c;别担心&#xff0c;我刚开始用的时候也这样。这个工具把数据库管理、浏览器界面和插件都集成在了一起&#xff0c;特别适合新手快速上手。安装过程我就不赘述了&#xff0…...

UE5 UI控件实战指南 —— 从基础到高级交互设计

1. UE5 UI控件基础入门 第一次打开UE5的UMG编辑器时&#xff0c;看到琳琅满目的控件面板可能会有点懵。别担心&#xff0c;我们先从最基础的Image和Text控件开始&#xff0c;就像学画画先从线条练起一样。 Image控件相当于你的画布。我习惯先在内容浏览器里右键创建"用户界…...

OpenClaw调试技巧:Qwen3-32B任务失败排查手册

OpenClaw调试技巧&#xff1a;Qwen3-32B任务失败排查手册 1. 为什么需要这份手册&#xff1f; 上周我尝试用OpenClaw自动整理项目文档时&#xff0c;遇到了一个诡异现象&#xff1a;同样的任务在白天能顺利完成&#xff0c;深夜运行时却频繁报错。经过72小时的问题追踪&#…...

高基数路由器的最佳拍档?深入浅出解析Flattened Butterfly拓扑的优缺点与适用场景

高基数路由器的最佳拍档&#xff1f;深入浅出解析Flattened Butterfly拓扑的优缺点与适用场景 在构建大规模互连网络时&#xff0c;拓扑结构的选择往往决定了系统的性能上限和成本下限。当工程师面对高基数路由器&#xff08;High-Radix Router&#xff09;的选型时&#xff0c…...

手把手教你为i.MX6ULL开发板适配非标准分辨率LCD(以1024x600 OV5640为例)

i.MX6ULL开发板非标准分辨率LCD适配实战&#xff1a;从寄存器配置到图像稳定输出 在嵌入式视觉系统开发中&#xff0c;摄像头与显示设备的适配往往成为项目落地的关键瓶颈。当面对非标准分辨率的LCD屏幕时&#xff0c;开发者需要深入理解图像采集与显示的全链路原理&#xff0c…...

OCLP-Mod:终极指南 - 让老旧Mac免费升级到最新macOS

OCLP-Mod&#xff1a;终极指南 - 让老旧Mac免费升级到最新macOS 【免费下载链接】OCLP-Mod A mod version for OCLP,with more interesting features. 项目地址: https://gitcode.com/gh_mirrors/oc/OCLP-Mod 你是否拥有一台被苹果官方"抛弃"的老旧Mac&#x…...

别再死记硬背Sarsa公式了!用Python手搓一个‘胆小’的迷宫探索AI(附完整代码)

用Python打造胆小如鼠的迷宫AI&#xff1a;Sarsa算法实战图解 当你在迷宫中小心翼翼地贴着墙走&#xff0c;生怕掉进陷阱时——恭喜&#xff0c;你已经理解了Sarsa算法的核心思想。今天我们不谈枯燥的数学公式&#xff0c;而是用Python构建一个会"瑟瑟发抖"的迷宫探索…...

从零搭建AI办公助手:OpenClaw+百川2-13B-4bits七日实践计划

从零搭建AI办公助手&#xff1a;OpenClaw百川2-13B-4bits七日实践计划 1. 为什么选择这个组合&#xff1f; 去年冬天&#xff0c;当我第一次听说OpenClaw这个开源自动化框架时&#xff0c;内心是充满怀疑的。作为一个长期被各种"智能助手"忽悠的技术从业者&#xf…...