SpringBoot 基础概念:注册BeanDefinition

Spring源码解析之【BeanFactory】与【BeanDefinitionRegistry】 在分析了Spring的源码之后发现,Spring里面用了很多的BeanFactory,这个类非常重要,因为实际上在Spring中BeanFactory是IOC容器的实际代表者,它用来创建和管理Bean。它为其他具体的IOC容器提供了最基本的规范,它是一个接口类型。 BeanFactory是最典型的工厂方法模式。不同类型的工厂会生产不同类型的商品。它的子接口和对应的实现类结构如下: 我们可以看到在... 阅读详情

1. 前言

问题:为什么需要注册BeanDefinition?
为了后续实例化。Spring架构是将Bean的定义信息注册流程和Bean的实例化过程分开的。
BeanDefinition就是对Bean的定义的信息,包含了class等信息。

2. BeanDefinitionReaderUtils#registerBeanDefinition

/**
 * Register the given bean definition with the given bean factory.
 * @param definitionHolder the bean definition including name and aliases
 * @param registry the bean factory to register with
 * @throws BeanDefinitionStoreException if registration failed
 */
public static void registerBeanDefinition(
		BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
		throws BeanDefinitionStoreException {

	// Register bean definition under primary name.
	String beanName = definitionHolder.getBeanName();
	registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

	// Register aliases for bean name, if any.
	String[] aliases = definitionHolder.getAliases();
	if (aliases != null) {
		for (String alias : aliases) {
			registry.registerAlias(beanName, alias);
		}
	}
}
  1. 该方法是注册BeanDefinition的工具方法。
  2. 参数:
    definitionHolder:是对BeanDefinition的封装,里面有beanName和aliases(bean的别名)。
    BeanDefinitiion:Bean的一些定义信息,包含class信息。
    registry:可以理解为DefaultListableBeanFactory。
  3. 将BeanDefinition注册到DefaultListableBeanFactory。将别名与beanName进行绑定,方便通过别名获取bean,别名与bean的名称是不能相互依赖的。

3. DefaultListableBeanFactory#registerBeanDefinition

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
		throws BeanDefinitionStoreException {

	Assert.hasText(beanName, "Bean name must not be empty");
	Assert.notNull(beanDefinition, "BeanDefinition must not be null");

	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Validation of bean definition failed", ex);
		}
	}

	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
		//如果已经注册了BeanDefinition,那么就判断是否循序覆盖,不允许覆盖则抛出异常
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		}
		else if (existingDefinition.getRole() < beanDefinition.getRole()) {
			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
			if (logger.isInfoEnabled()) {
				logger.info("Overriding user-defined bean definition for bean '" + beanName +
						"' with a framework-generated bean definition: replacing [" +
						existingDefinition + "] with [" + beanDefinition + "]");
			}
		}
		else if (!beanDefinition.equals(existingDefinition)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		//注册BeanDefinition
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	else {
		//没有注册相同的BeanDefinition
		if (hasBeanCreationStarted()) {
			//已经开始了实例化Bean
			// Cannot modify startup-time collection elements anymore (for stable iteration)
			synchronized (this.beanDefinitionMap) {
				//使用了copyOnWrite原理,读写分离地去注册BeanDefinition
				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
			//如果依然在注册BeanDefinition的阶段,那么就直接去注册BeanDefinition
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			//移除了手动注册的单例名称
			removeManualSingletonName(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	//如果单例池中已经注册了相同的实例,那么就重置BeanDefinition
	if (existingDefinition != null || containsSingleton(beanName)) {
		resetBeanDefinition(beanName);
	}
}
  1. 如果已经注册了BeanDefinition,那么就判断是否循序覆盖,不允许覆盖则抛出异常。是否允许覆盖是在spring.main.allow-bean-definition-overriding配置,在SpringBoot启动流程中有讲解。
    SpringBoot 源码解析2:启动流程
  2. 如果已经该是实例化Bean的流程,那么就使用copyOnWrite原理注册BeanDefinition和beanName。因为Bean的实例化流程可能是用户多线程去getBean的,就会引发线程安全问题。
  3. 如果没有开始实例化流程,那么就直接注册BeanDefinition和BeanName。
  4. 移除了手动注册的beanName,Spring原则是优先使用用户配置,再使用内部默认配置。
  5. 如果单例池中已经注册了相同的实例,那么就重置BeanDefinition,即删除单例池中的对象,重新注册BeanDefinition,后续重新去实例化。
SpringBoot的Bean Definition 生成过程(源码分析) 1、目的: 从源码的角度分析整个springboot的启动流程、了解springboot项目在整个启动过程都干了一些什么。 因为spring项目的启动主要是分为两步,一个是bean definition的获取,一个是根据bean definition 生成bean。本篇主要涉及 2、demo项目结构的简单描述。 基本的东西都是有的,包括dao,service、model、且包含myba... 阅读详情

相关推荐

Verilog仿真必备:FSDB dump命令全解析与实战配置指南

本文深入解析了Verilog仿真中FSDB波形记录的核心命令与实战配置技巧。针对大规模SoC验证场景,详细介绍了如何通过$fsdbDumpvars、$fsdbDumpfile等命令实现信号精准捕获、文件体积控制和动态启停,并提供了智能化的分层dump策略,帮助工程师在保证调试信息完整性的同时,大幅提升验证效率并有效管理波形数据。

cnn8visionary的博客 347

Spring源码学习(八)---注册BeanDefinition

这里主要是使用org.springframework:spring-beans:5.2.0.RELEASE进行分析 文章目录 1. 查看源码相关的快捷键 快捷键 作用 Ctrl + Shift+i 出现类似于预览的小窗口 Ctrl + Enter (接上步)完全打开源码 Ctrl + 鼠标左键 一步到位打开源码 = Ctrl + Shift+i –>Ctrl + Enter Alt+7 查看类的有什么方法 ctrl+f12 查看继承方法 ctrl+h 查看接口的实.

1170

SAP PS模块预算控制实战:为什么你的采购订单金额和预算占用对不上?

本文深入解析SAP PS模块中采购订单金额与预算占用偏差的常见问题,揭示承诺成本与实际成本的分流处理机制。通过实战案例和六步定位法,提供发票拆分、跨年度预算等典型场景的解决方案,并分享预防性配置框架和最佳实践,帮助企业有效控制预算偏差。

weixin_30363981的博客 515

spring frmework源码分析

子路老师2021版spring源码深度分析,由于之前两个版本的spring源码课程是在公司里面录制的,存在很多局限性(时间、讲课方式)也存在很多不合理的地方;这次把spring源码课程进行了一次重制;属于子路老师个人行为,内容更加的丰富,知识更加深入;也纠正了以前版本的一些错误。之前的课程基本是围绕spring bean的生命周期周边进行讲解,这次重制之后除了对bean的生命周期更加入了很多以前没有涉及到的知识;比如ASM的扫描原理,spring扫描器的扩展原理,beanFactory的各种api、以及spring cloud对spring的扩展等等;内容和深度也是之前版本的5倍以上,真正的对spring源码逐行分析;可以让你学完之后对spring源码有更加深入了解,在面试中轻松对答,在工作中轻松实现对spring的扩展;成为真正的spring大师。这里是部分课程的内容截图 以及部分源码的注释   

Vue中实现word文档渲染、在线编辑、保存

Vue3对word文档进行渲染、编辑、保存。word转成html,html转成word

h18749849699的博客 1328

LabView实战:精准实现float到十六进制的转换与高低位拆分

本文详细讲解了在LabVIEW中实现单精度浮点数(float)到十六进制字符串转换,并进行高低16位拆分的实战方法。针对工业通信中设备协议要求,核心使用强制类型转换(Type Cast)获取内存原始数据,避免数值转换错误,并提供了完整的VI构建步骤、交叉验证技巧及常见踩坑经验(如字节序、字符串格式),确保数据通信的准确性。

assembly8low的博客 1765

spring5源码篇(2)——BeanDefinition的注册

spring5源码篇之BeanDefinition的注册

笔记罢了 1740

通达信主力检测利器

主力轨迹:100*EMA(EMA(MTM,N1),N1)/EMA(EMA(ABS(MTM),N1),N1),COLORWHITE;主力拉高:IF(VAR51<REF(VAR51,1),VAR51,0),COLORYELLOW,NODRAW;洗盘:IF(VAR5<REF(VAR5,1),VAR5,0),COLOR000079,NODRAW;主力进场:IF(VAR5>REF(VAR5,1),VAR5,0),COLORRED,NODRAW;MAZL:MA(主力轨迹,N2),COLORYELLOW;

zhibiaogong的博客 7451

3. Springboot2启动过程源码分析-prepareContext方法

系列文章目录 1.Springboot2启动过程源码分析-SpringApplication初始化 2.Springboot2启动过程源码分析-SpringApplication#run 3.Springboot2启动过程源码分析-prepareContext方法 4.Springboot2启动过程源码分析-refresh方法 5.Springboot2启动过程源码分析-Bean的实例化 6.Springboot2启动过程源码分析-总结 文章目录 系列文章目录 前言 prepar.

万般皆苦,唯有自渡 5396

12、多旋翼飞行器动力学建模与实验分析

本文探讨了多旋翼飞行器的动力学建模过程,包括使用四元数的优势、刚体运动学与动力学模型的构建,以及螺旋桨推力和扭矩对飞行性能的影响。文章还通过基础实验和分析实验研究了质量、转动惯量和螺旋桨参数对飞行状态和控制响应的影响,并结合理论分析与仿真结果总结了多旋翼飞行器的动力学特性。最后,对未来研究方向进行了展望,以提升多旋翼飞行器的性能和可靠性。

Python的专栏 207

【Unity3D插件】XCharts插件完全教程《全网最全》-专栏文章目录

最近在做图表类需求功能的时候,发现了一款强大的Unity3D插件,也就是XCharts图表插件,功能强大,支持多种图表。官方介绍:一款基于UGUI的功能强大、简单易用的数据可视化图表插件。支持折线图、饼状图、饼图、雷达图、散点图、热力图、环形图、K线图、极坐标、平行坐标等十多种内置图表,以及3D饼图、3D金字塔、漏斗图、仪表盘、水位图、象形柱图、甘特图、矩形树图等拓展图表。内置丰富示例和模板,参数可视化配置,效果实时预览,纯代码绘制。支持折线图、柱状图、饼图、雷达图、散点图、热力图等常见图表。

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 3194

SpringBoot成长记5:Spring容器的创建

前面你熟悉了SpringBoot的扩展点SpringApplicationRunListeners的设计,配置文件ConfigurableEnvironment的抽象封装。其实这些都还不是它最核心的,最最核心的时Spring的容器的创建和准备,自动配置的装配,tomcat的容器的启动。 这一节我们就来开始研究Spring的容器相关的逻辑,看看它有什么抽象的设计和扩展点,又主要做了哪一些事情呢? public ConfigurableApplicationContext run(String... args.

繁茂的博客 623

R语言缺失值填补|插值法、均值法、邻近法

本文主要介绍如何利用R语言进行数值型缺失值的填补。主要使用zoo包中的na.aggregate() 、na.approx()、na.locf() 函数进行缺失值的均值填补、线性插值填补以及邻近值填补。

Mrrunsen的博客 3841

Spring源码阅读——笔记整理

Spring源码阅读,学习笔记记录。 更多内容,欢迎关注vx公众号:豆萌萌 网课大咖

xrq19950928的博客 413

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

SpringBoot中BeanDefinition的注册顺序

SpringBoot BeanDefinition的注册顺序 为什么要了解BeanDefinition的注册顺序 在spring中了解BeanDefinition的注册顺序可以更好的把握Bean的创建顺序,当在beanFactory.getBean()抛出Bean不存在的时候,就说明在那个时刻BeanFactory中并没有那个BeanDefinition的存在,或许在之后会被注册到BeanFactoy中,之所以会出现这个错误是因为,在获取这个Bean的时候不存在这个Bean的BeanDefinition。

Hhd2233的博客 1380

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

spring boot自动装载的设计思想

为什么要有反射机制这个东西当我们使用new实例化对象时,时再jvm加载时就开始创建对象,分配内存空间,当我们将所有对象都使用new进行实例化时,再程序启动后,jvm加载完成,堆内存中就已经存在了大量的对象,占用了大量的内存空间,有些业务可能并不常用,导致有些对象也会并不常用,但是由于new的对象时强引用,gc并不会回收对象,导致大量内存被这些不常用对象占用,这个叫做静态编译。如果将对象实例化的过程并不放在JVM加载过程中,二十再使用的时候才去申请内存空间,创建对象,就可以再jvm启动的时候,节省大量类的初始

伤何 381

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

spring注册beanDefinition

代码使用springboot测试。

weixin_46666822的博客 1110

【springboot源码分析】3.BeanDefinition注册

springboot对BeanDefinition进行注册发生在对工厂后置处理器调用中,调用链是 run(…)->refreshContext(…)->refresh()->invokeBeanFactoryPostProcessors(beanFactory),refresh方法执行是springboot启动最核心的部分 public void refresh() throw...

xia744510124的专栏 319

Spring boot 加载和注册 BeanDefinition

Spring Boot 加载 BeanDefinitions 的核心流程贯穿了容器的初始化过程。BeanDefinition 是 Spring 容器中描述 Bean 元数据的对象,包含类名、作用域、懒加载、初始化方法等信息。Spring Boot 通过 SpringApplication.run() 方法启动应用,该过程包括资源定位、解析配置文件和注册 BeanDefinition 等步骤。具体流程如下: 启动入口:通过 SpringApplication.run(Application.class, ar

红血哥 1729

SpringBoot启动过程(三)class 变成 beanDefinition

Spring Boot 在启动是执行了自动配置:class --> beanDefinition --> bean。这篇文章主要想梳理下:class 是怎么变成 beanDefinition 的。上一篇博客提到过,执行 run 方法中 invokeBeanFactoryPostProcessors(beanFactory) 方法执行了这一变换,看下这个方法了到了干了什么? 1. invokeBeanFactoryPostProcessors /** AbstractApplicationCont

骑着蜗牛向前跑的博客 1618

SpringBoot自动装配原理(到注册beanDefinition)

SpringBoot自动装配原理(到注册beanDefinition) 总体结构:return (new SpringApplication(primarySources)).run(args); new SpringApplication(primarySources public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.sources = new Linke

qq_40506747的博客 674

SpringBean动态注册BeanDefinition(三)

SpringBean动态注册BeanDefinition(三)

MostSnails的博客 2011

SpringBoot源码学习——BeanDefinition注册以及@Configuration的解析

BeanDefinition——spring bean的建模对象 那么什么是spring bean的建模对象呢?一言概之就是把一个bean实例化出来的模型对象?有人会问把一个bean实例化出来有Class就行了啊,Class也就是我们通常说的类对象,就是一个普通对象的建模对象,那么为什么spring不能用Class来建立bean呢?很简单,因为Class无法完成bean的抽象,比如bean的作用域,bean的注入模型,bean是否是懒加载等等信息,Class是无法抽象出来的,故而需要一个BeanDefini

XHY的博客 647

【spring】beanDefinition 具体是什么时候注册到BeanFactory的

解疑:beanDefinition 会什么时候注册到beanfactory的

u010592926的专栏 655

SpringBoot 刷新上下文6--加载并注册BeanDefinition

SpringBoot 刷新上下文6

xuwenjingrenca的博客 494

注册Spring Bean:如何将BeanDefinition注册到IoC容器?

Spring 是如何将BeanDefinition注册到容器,到底我们有多少种方法来操作? 本篇主要围绕这两个议题通过不同的维度来进行讨论,下面是我主要罗列了几种不同的实现方案 XML 配置 Java 注解配置元信息 Java API 配置元信息 看过Spring 源码的朋友应该注意到这里还有一种配置方式就是关于Properties文件的一个配置方法,这里不做展开后续再做介绍 简要说明 第一种方式:我们可以看出一个特点是我们的Bean的名称是通过XML元素内属性...

码农架构 650
上一篇: SpringBoot 源码解析5:ConfigurationClassPostProcessor整体流程和@ComponentScan源码分析
下一篇: SpringBoot 源码解析6:Bean的创建① AbstractBeanFactory#doGetBean
hao9e
博客等级 码龄7年 189粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值