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中,EnableAutoConfiguration注解用于开启自动装配功能。 本文将详细分析该注解的工作流程。 EnableAutoConfiguration注解 启用SpringBoot自动装配功能,尝试猜测和配置可能需要的组件Bean。 自动装配类通常是根据类路径和定义的Bean来应…...
ansible-roles模块
roles用于层次性,结构化地组织playbook,roles能够根据层次型结构自动装载变量文件,tasks以及handlers等。要使用只要载playbook中使用include指令引入即可。 (roles就是通过分别将变量,文件,任务ÿ…...
聊聊我做 NeRF-3D重建性能优化经历
我们新推出大淘宝技术年度特刊《长期主义,往往从一些小事开始——工程师成长总结专题》,专题收录多位工程师真诚的心路历程与经验思考,覆盖终端、服务端、数据算法、技术质量等7大技术领域,欢迎一起沟通交流。 本文为此系列第四篇…...
未磁科技全球首台64通道无液氦心磁图仪及首个培训基地落户北京安贞医院
【全球首台64通道无液氦心磁图仪在北京安贞医院举行开机仪式】 近日,在北京安贞医院举行了未磁科技全球首台64通道无液氦心磁图仪开机仪式,中国医学装备协会赵自林理事长、北京安贞医院纪智礼书记、张宏家院长、宋现涛教授,以及未磁科技蔡宾…...
SpringBoot 如何使用 ApplicationEventPublisher 发布事件
SpringBoot 如何使用 ApplicationEventPublisher 发布事件 在 SpringBoot 应用程序中,我们可以使用 ApplicationEventPublisher 接口来发布事件。事件可以是任何对象,当该对象被发布时,所有监听该事件的监听器都会收到通知。 下面是一个简单…...
【深度学习】2-3 神经网络-输出层设计
前馈神经网络(Feedforward Neural Network),之前介绍的单层感知机、多层感知机等都属于前馈神经网络,它之所以称为前馈(Feedforward),或许与其信息往前流有关:数据从输入开始,流过中间计算过程,最后达到输出…...
Python网络爬虫开发:使用PyQt5和WebKit构建可定制的爬虫
部分数据来源:ChatGPT 引言 在网络爬虫开发中,使用Web浏览器模拟用户行为是非常重要的。而在这个过程中,基于 WebKit 的框架可以提供比其他技术更紧密的浏览器集成,以及更高效、更多样化的页面交互方式。 在本文中,我们将通过一个使用基于 WebKit 的爬虫示例,并与类似…...
Laya3.0游戏框架搭建流程(随时更新)
近两年AI绘图技术有了长足发展,准备把以前玩过的游戏类型重制下,也算是圆了一个情怀梦。 鉴于unity商用水印和启动时间的原因,我决定使用Laya来开发。目前laya已经更新到了3.0以上版本,就用目前比较新的版本。 之后关于开发中遇到…...
.net 软件开发模式——三层架构
三层架构是一种常用的软件开发架构模式,它将应用程序分为三个层次:表示层、业务逻辑层和数据访问层。每一层都有明确的职责和功能,分别负责用户交互、业务处理和数据存储等任务。这种架构模式的优点包括易于维护和扩展、更好的组织结构和代码…...
SpringBoot如何优雅的实现重试功能
文章目录 使用背景spring-retry介绍快速使用加入依赖开启Retry使用参数 使用背景 在有些特定场景,如和第三方对接。 我们调用接口时需要支持重试功能,第一次调用没成功,我们需要等待x秒后再次调用。 通常会设置重试次数,避免业务…...
【CEEMDAN-VMD-GRU】完备集合经验模态分解-变分模态分解-门控循环单元预测研究(Python代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
OpenText Exceed TurboX(ETX)—— 适用于 UNIX、Linux 和 Windows 的远程桌面解决方案
由于新技术的采用,以及商业全球化和全球协作的现实,几乎所有企业(无论其规模和所处行业)的员工的工作方式、时间和地点都发生了重大变化。业务领导者正在推动其 IT 部门提出解决方案,以帮助其远程员工提高工作效率&…...
【人工智能】— 逻辑回归分类、对数几率、决策边界、似然估计、梯度下降
【人工智能】— 逻辑回归分类、对数几率、决策边界、似然估计、梯度下降 逻辑回归分类Logistic Regression ClassificationLogistic Regression: Log OddsLogistic Regression: Decision BoundaryLikelihood under the Logistic ModelTraining the Logistic ModelGradient Desc…...
k8s pod “cpu和内存“ 资源限制
转载用于收藏学习:原文 文章目录 Pod资源限制requests:limits:docker run命令和 CPU 限制相关的所有选项如下: Pod资源限制 为了保证充分利用集群资源,且确保重要容器在运行周期内能够分配到足够的资源稳定运行&#x…...
datagrip 连接 phoenix
jar替换完后尽量重启datagrip. 然后重新连接即可. 不重启貌似报错... 效果:...
黑客入侵的常法
1.无论什么站,无论什么语言,我要渗透,第一件事就是扫目录,最好一下扫出个上传点,直接上传 shell ,诸位不要笑,有时候你花很久搞一个站,最后发现有个现成的上传点,而且很容…...
VB报警管理系统设计(源代码+系统)
可定时显示报警系统是一个能够定时并及时报警,提醒人们安全有效地按计划完成任务的系统。本论文从软件工程的角度,对可定时显示报警系统做了全面的需求分析,简要说明了该系统的构思、特点及开发环境;阐述了系统的主要功能,论述了它的设计与实现,并且叙述了系统的测试与评…...
Redis入门 - Redis Stream
原文首更地址,阅读效果更佳! Redis入门 - Redis Stream | CoderMast编程桅杆Redis入门 - Redis Stream Redis Stream 是 Redis 5.0 版本新增加的数据结构。 Redis Stream 主要用于消息队列(MQ,Message Queue)…...
微服务中常见问题
Spring Cloud 组件 Spring Cloud五大组件有哪些? Eureka:注册中心 Ribbon:负载均衡 Feign:远程调用 Hystrix:服务熔断 Zuul/Gateway:服务网关 随着SpringCloud Alibaba在国内兴起,我们项目中…...
更新删除清理购物车
目录 1 更新购物车 2 取会员门店购物车项 3 取会员门店购物车项(无缓存) 4 删除门店购物车某项 5 删除门店购物车多项 6 清理门店购物车 7 清理门店购物车 8 添加商品至购物车 9 添加商品至购物车...
基于Intel NUC平台的字符设备陀螺仪GX5-25驱动程序
陀螺仪GX5-25连接到Intel NUC上可能需要进行一些设备树的修改和编写驱动程序的工作。这是因为陀螺仪GX5-25可能需要特定的设备树配置和驱动程序来与Intel NUC的硬件和操作系统进行通信。 如果陀螺仪GX5-25没有官方的Linux驱动程序或文档,您可能需要自己编写驱动程序…...
建立小型医学数据库(总结)
建立小型医学数据库 小型医学数据库可以用于存储和管理医学数据,如患者病历、药品信息、试验结果等。这对于医疗机构和科研机构来说非常必要,可以提高数据管理和共享的效率,进而促进医学研究和诊疗水平的提升。 建立小型医学数据库有以下基本…...
Git学习笔记
文章目录 一. 引入1. SCM软件2. 概念 二. GitHubDesktop三. Git1. 版本号 (底层原理)1.1 视频笔记1.2 实操记录 2. Git命令2.0 汇总2.1 仓库操作2.2 文件操作2.3 分支操作2.4 标签操作2.5 远程仓库 四. idea操作 一. 引入 1. SCM软件 2. 概念 集中式版本控制 文件冲突 可以上…...
vue面试题1. 请说下封装 vue 组件的过程?2. Vue组件如何进行传值的?3. Vue 组件 data 为什么必须是函数?4. 讲一下组件的命名规范
1. 请说下封装 vue 组件的过程? 首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。 分析需求:确定业务需求,把页面中可以…...
Docker使用记录
文章目录 Docker基本使用Docker配置查看状态卸载安装使用 apt 存储库安装在 Ubuntu 上安装 Docker 桌面(非必要) Docker实例使用现有的镜像查找镜像拖取镜像列出镜像列表更新镜像导出镜像删除镜像导入镜像清理镜像查看容器导出容器导入容器-以镜像的方式创建容器重启容器进入容…...
OpenCV(图像处理)-基于Python-形态学处理-开运算、闭运算、顶帽、黑帽运算
1. 形态学2. 常用接口2.1 cvtColor()2.2 图像二值化threshod()自适应阈值二值化adaptiveThreshod() 2.3 腐蚀与膨胀erode()getStructuringElement()dilate() 2.4开、闭、梯度、顶帽、黑帽运算morphologyEx() 1. 形态学 OpenCV形态学是一种基于OpenCV库的数字图像处理技术&…...
chatgpt赋能python:Python支持跨平台软件开发
Python支持跨平台软件开发 作为一种高级编程语言,Python 以其丰富的库和跨平台支持而备受开发人员欢迎。Python 通过将应用程序的可移植性最大化,使得开发人员可以轻松地在不同的操作系统平台上构建和部署软件。 跨平台支持 Python 支持各种不同的操作…...
哈工大计算机网络课程网络层协议详解之:CIDR与路由聚集
哈工大计算机网络课程网络层协议详解之:CIDR与路由聚集 文章目录 哈工大计算机网络课程网络层协议详解之:CIDR与路由聚集CIDR与路由聚集CIDR路由聚集 CIDR与路由聚集 CIDR CIDR:无类域间路由(CIDR:Classless InterDo…...
C++ 教程(19)——日期 时间
C 日期 & 时间 C 标准库没有提供所谓的日期类型。C 继承了 C 语言用于日期和时间操作的结构和函数。为了使用日期和时间相关的函数和结构,需要在 C 程序中引用 <ctime> 头文件。 有四个与时间相关的类型:clock_t、time_t、size_t 和 tm。类型…...
React 应用 Effect Hook 函数式中操作生命周期
React Hook入门小案例 在函数式组件中使用state响应式数据给大家演示了最简单的 Hook操作 那么 我们继续 首先 Hook官方介绍 他没有破坏性是完全可选的 百分比兼容 也就说 我们一起的 类 class的方式也完全可以用 只要 react 16,8以上就可以使用 Hook本身不会影响你的react的理…...
想自己做个网站/免费网站排名优化软件
金庸笔下的良好代码风格 转至:http://kb.cnblogs.com/page/202642/作者: 王路 发布时间: 2014-03-23 14:00 阅读: 8964 次 推荐: 43 原文链接 [收藏] 我零九年看过一本小说,讲程序员的故事,从此,了解了一个新物种。最近又…...
开发网站私活/关键字c语言
因为最近的多元统计讲到了聚类分析,课上同学也分别同R、SPSS、python展示了简单的聚类。但是问题是,理论不够联系实际,具体说,就是我们没有结合具体的业务背景,甚至连数据清洗的环节也直接略过了࿰…...
镇网站建设管理工作总结/郑州网站营销推广公司
async/await Task Timeout 在日常的电脑使用过程中,估计最难以忍受的就是软件界面“卡住”“无响应”,在我有限的开发生涯中一直都是在挑战 它。在WPF中,主线程即UI线程,当我们在UI线程中执行一个很耗时的操作,以至于UI线程没能继…...
用路由器做简单的网站/产品营销策略怎么写
字符串函数是最常用的的一种函数,在一个具体应用中通常会综合几个甚至几类函数来实现相应的应用:1、LOWER(column|str):将字符串参数值转换为全小写字母后返回MySQL> select lower(SQL Course);---------------------| lower(SQL Course) …...
十度公司做网站怎么样/网站的优化
前言 最近需要设计大量RESTful的接口,之前对RESTful只是了解,没系统学习过ta的设计方法。借到一本《RESTful Web Services Cookbook》,也算是RESTful接口设计的经典著作了,书挺厚,本文记录下我认为重要的、易忘的知识点…...
做算法题的 网站/公司软文推广
早就听说需求分析这个环节是重中之重,看看他人之前做过的一些产品实践案例,这样学起来更快。以一款APP为例,阐述了需求痛点及其解决方案,我们姑且叫这个App为TT吧。TT是一个面向食品供应商的、以试吃为特色的社会化食品电商导购平…...