Spring Bean的顺序

news2024/12/24 9:57:54

之前的文章已经讲过,Spring Bean的创建是通过动态代理实现的,防止浪费篇幅,我们直接看Bean的循环创建代码;

这里我们可以看到 Bean 的创建是通过:

List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
    // Create Bean Code....
}

Bean的创建顺序其实就是this.beanDefinitionNames的顺序。

可以看出this.beanDefinitionNames又是List<?>类型,所以顺序源自add(obj)的顺序。那this.beanDefinitionNames又是怎么填充的呢?

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
    // 省略部分代码,直接进入BeanName的add过程.....
    else {
    	if (hasBeanCreationStarted()) {
    		// Cannot modify startup-time collection elements anymore (for stable iteration)
    		synchronized (this.beanDefinitionMap) {
    			this.beanDefinitionMap.put(beanName, beanDefinition);
    			List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
    			updatedDefinitions.addAll(this.beanDefinitionNames);
    			updatedDefinitions.add(beanName);
    			this.beanDefinitionNames = updatedDefinitions;
    			removeManualSingletonName(beanName);
    		}
    	}
    	else {
    		// Still in startup registration phase
    		this.beanDefinitionMap.put(beanName, beanDefinition);
    		this.beanDefinitionNames.add(beanName);
    		removeManualSingletonName(beanName);
    	}
    	this.frozenBeanDefinitionNames = null;
    }
    // 省略后续代码...
    
}

再追溯一下org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinitionorg.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForBeanMethod中使用到

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
	TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
	for (ConfigurationClass configClass : configurationModel) {
		loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
	}
}

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
	// 省略....
	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
		loadBeanDefinitionsForBeanMethod(beanMethod);
	}
    // 省略....
}

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
    // 省略...
    this.registry.registerBeanDefinition(beanName, beanDefToRegister);
    // 省略...
}

继续向下找到具体的地方:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    // 省略部分代码..
	processConfigBeanDefinitions(registry);
}

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    // 省略部分代码....    
    // Parse each @Configuration class
	ConfigurationClassParser parser = new ConfigurationClassParser(
	    this.metadataReaderFactory, this.problemReporter, this.environment,
		this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    do {
        parser.parse(candidates);
        parser.validate();
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);
        // Read the model and create bean definitions based on its content
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                registry, this.sourceExtractor, this.resourceLoader, this.environment,
                this.importBeanNameGenerator, parser.getImportRegistry());
        }
        this.reader.loadBeanDefinitions(configClasses);
        // 省略部分代码...
    }
    while (!candidates.isEmpty());
    // 省略部分代码...
}

至此,我们基本可以看出来,BeanNames的顺序是由org.springframework.context.annotation.ConfigurationClassPostProcessor决定的,而ConfigurationClassPostProcessor由实现了BeanDefinitionRegistryPostProcessor,其核心就是将代码中注册@Configuration注解的类以及经由此配置类注册的Bean解析为BeanDefinition,而这一步是在refresh()invokeBeanFactoryPostProcessors(beanFactory);完成的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/464183.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux服务使用宝塔面板搭建网站,并发布公网访问 - 内网穿透(1)

文章目录 前言1. 环境安装2. 安装cpolar内网穿透3. 内网穿透4. 固定http地址5. 配置二级子域名6. 创建一个测试页面 转载自远程内网穿透的文章&#xff1a;Linux使用宝塔面板搭建网站&#xff0c;并内网穿透实现公网访问 前言 宝塔面板作为简单好用的服务器运维管理面板&#…

el-input 只能输入整数(包括正数、负数、0)或者只能输入整数(包括正数、负数、0)和小数

使用el-input-number标签 也可以使用typenumbe和v-model.number属性&#xff0c;两者结合使用&#xff0c;能满足大多数需求&#xff0c;如果还不满足&#xff0c;可以再结合正则表达式过滤 <el-input v-model.number"value" type"number" /> el-i…

孙溟㠭先生篆刻欣赏——“数”

孙溟㠭篆刻作品《数》 孙溟㠭篆刻作品《数》 线条之美可见一斑。游龙戏凤&#xff0c;嬉戏又雅趣。此时溟㠭先生之心境又如何&#xff1f; 人生几多戏谑&#xff0c;世事几多无常&#xff1b;趣心对待&#xff0c;过而无痕。何必拘束&#xff1f;何必强求规矩&#xff1f;突…

测量射频器件噪声系数的三种方法盘点

本文介绍了测量噪声系数的三种方法&#xff1a;增益法、Y系数法和噪声系数测试仪法。这三种方法的比较以表格的形式给出。 在无线通信系统中&#xff0c;噪声系数&#xff08;NF&#xff09;或者相对应的噪声因数(F)定义了噪声性能和对接收机灵敏度的贡献。本篇应用笔记详细阐…

P1043 [NOIP2003 普及组] 数字游戏

题目描述 丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单&#xff0c;但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的&#xff0c;在你面前有一圈整数&#xff08;一共 &#xfffd;n 个&#xff09;&#xff0c;你要按顺序…

Java List、Set、Map区别

概述 集合类存放于java.util包中。集合类存放的都是对象的引用&#xff0c;而非对象本身。常见的集合主要有三种——Set(集&#xff09;、List&#xff08;列表&#xff09;和Map&#xff08;映射&#xff09;。List和Set 都实现了 Collection 接口&#xff0c;并且List和Set也…

php执行语句在MySQL批量插入大数据量的解决方案及计算程序执行时间(大数据量、MySQL语句优化)

MySQL里批量插入大数据的解决方案 前言一、PHP计算程序执行时间二、Mysql批量插入数据1.INSERT INTO 语句2.批量插入大数据2.1 使用循环$sql的方式2.2 循环(值1, 值2,....)的语句2.3测试过程出现的错误 前言 近期在MySQL报表开发过程中&#xff0c;需要爬取多API返回JSON数据&…

MySql中执行计划如何来的——Optimizer Trace | 京东云技术团队

作者&#xff1a;京东物流 籍磊 1.前言 当谈到MySQL的执行计划时&#xff0c;会有很多同学想&#xff1a;“我就觉得使用其他的执行方案比EXPLAIN语句输出的方案强&#xff0c;凭什么优化器做的决定与我得不一样&#xff1f;”。这个问题在MySQL 5.6之前或许自己很难解决&…

真题详解(磁盘)-软件设计(五十八)

真题详解&#xff08;MTTR&#xff09;-软件设计&#xff08;五十七)https://blog.csdn.net/ke1ying/article/details/130354940 1、2021年上半年 解析&#xff1a; 哈希地址 0 1 2 3 4 5 6 7 8 9 10 构建哈希表 第一步&#xff1a;3%11 3 &#xff0c;放在哈希地址3的位置…

如何申请gpt4.0-如何接入ChatGPT4

如何接入ChatGPT4 ChatGPT-4是OpenAI公司推出的最新自然语言处理技术&#xff0c;采用深度学习算法&#xff0c;旨在提供更加高效、准确的人工智能语言处理能力。如果您想要接入ChatGPT-4&#xff0c;您可以按照以下步骤&#xff1a; 注册OpenAI账号并申请API密钥&#xff1a;…

2022年NOC大赛创客智慧编程赛道Python初赛题,包含答案

目录 一、单选题 二、多选题 三、判断题 下载文档打印做题: NOC Python 初赛考题 一、单选题 <

【c语言】typedef的基本用法 | 定义格式

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…

【图像分割】【深度学习】SAM官方Pytorch代码-Image encoder模块Vision Transformer网络解析

【图像分割】【深度学习】SAM官方Pytorch代码-Image encoder模块Vision Transformer网络解析 Segment Anything&#xff1a;建立了迄今为止最大的分割数据集&#xff0c;在1100万张图像上有超过1亿个掩码&#xff0c;模型的设计和训练是灵活的&#xff0c;其重要的特点是Zero-s…

从Domino目录导出你想要的信息

大家好&#xff0c;才是真的好。 无论出于什么原因&#xff0c;很多时候&#xff0c;我们要从Domino目录&#xff08;names.nsf&#xff09;中导出人员、群组或Domino相关的配置信息。不过更多时候&#xff0c;还没开始导&#xff0c;很多人就说Domino封闭&#xff0c;不让导出…

由浅入深MFC学习摘记--第四部分下

目录 第十三章 多文件与多显示MDI 和 SDI动态拆分窗口静态拆分窗口拆分 拆分窗口示例同源子窗口CMDIFrameWnd::OnWindowNew范例程序 多文件 第十四章 MFC 多线程从操作系统层面看执行线程线程优先级从程序设计层面看执行线程MFC 多线程程序设计工作线程UI线程执行线程的结束线程…

CASAIM 自动化3d测量系统检测压缩机壳体尺寸偏差/装配验证

压缩机是一种将低压气体提升为高压气体的从动的流体机械&#xff0c;是制冷系统的心脏。 压缩机的壳体共有三部份组成&#xff1a;排气壳体&#xff08;主要是组成压缩机排气通道及接口&#xff09;&#xff0c;机体壳体&#xff08;主要是组成压缩机的涡盘、涡盘支承座、电机…

Bladex后端实现登入时间过期后自动跳转登入页

Bladex后端实现登入时间过期后自动跳转登入页 背景现状期待成果解决方法一找到鉴权配置页面重写拦截器addInterceptors创建CustomMiddleware编制拦截逻辑修改登入有效时常 背景现状 Bladex可手动设置过期时间&#xff0c;但是我使用的是springboot BladeX 2.8.1.RELEASE版本&am…

游戏测试的面试技巧

游戏测试的面试技巧 1.自我介绍 回答提示&#xff1a;一般人回答这个问题过于平常&#xff0c;只说姓名、年龄、爱好、工作经验 &#xff0c;这些在简历上都有&#xff0c;其实&#xff0c;企业最希望知道的是求职者能否胜任工作&#xff0c;包括&#xff1a;最强的技能、最深入…

docker镜像创建|实战案例(ssh|systemd|nginx|apache|tomcat)

docker镜像创建|实战案例&#xff08;ssh|systemd|nginx|apache|tomcat&#xff09; 一 Docker 镜像的创建1.基于现有镜像创建2基于本地模板创建3 基于Dockerfile 创建为什么Docker里的centos的大小才200M&#xff1f;DockerfileDocker 镜像结构的分层 4 Dockerfile 案例&#…

宝光股份 | 打造营销管理数据平台,实现营销管理和业务双提升

陕西宝光真空电器股份有限公司&#xff08;以下简称“宝光股份”&#xff09;&#xff0c;注册资本3.3亿元&#xff0c;于2002年1月在上海证券交易所上市&#xff08;股票代码&#xff1a;600379&#xff09;。 宝光股份已发展成为享誉国内外的真空灭弧室产销基地&#xff0c;…