当前位置: 首页 > 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 添加商品至购物车...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...