Spring 源码阅读 04:BeanFactory 初始化

ApplicationContext系列三加载BeanFactory ApplicationContext是对BeanFactory的功能扩展,不但包含了BeanFactory的全部功能,还添加了其他扩展能力。obtainFreshBeanFactory方法是实现BeanFactory的地方,经过这个函数后,ApplicationContext就有了BeanFactory的全部功能。 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //初始化beanFactory,读取xm. 阅读详情

在之前的ApplicationContext 初始化 Spring 容器 一文中,我们提到了 AbstractApplicationContext#refresh 方法是一个非常重要的方法,它包含了 Spring 容器初始化的整个流程,我们将对这里的源码进行细致地阅读。本篇要阅读的是 BeanFactory 初始化的部分,也就是 refresh 方法中的这一行方法调用:

// Tell the subclass to refresh the internal bean factory.
// 这里会调用模版方法,通过子类的实现,初始化 BeanFactory 并解析 XML 配置
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

这里调用了 obtainFreshBeanFactory 并得到了一个 ConfigurableListableBeanFactory 类型的 beanFactory。这个方法的作用是初始化 beanFactory ,还会解析 XML 中配置的 Bean。

我们先看源码:

 /**
* Tell the subclass to refresh the internal bean factory.
*  @return  the fresh BeanFactory instance
*  @see  #refreshBeanFactory()
*  @see  #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   refreshBeanFactory();
   return getBeanFactory();
}

这个方法的源码很简单,调用了两个方法,并将第二个方法的结果返回。根据方法的名称可以看到,第一个方法用来刷新(或者初始化)beanFactory,第二个方法用来获取 beanFactory 并返回。

refreshBeanFactory 方法

我们先看 refreshBeanFactory 方法,具体实现过程可以在 AbstractRefreshableApplicationContext 类找到 :

 /**
* This implementation performs an actual refresh of this context's underlying
* bean factory, shutting down the previous bean factory (if any) and
* initializing a fresh bean factory for the next phase of the context's lifecycle.
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      beanFactory.setSerializationId(getId());
      customizeBeanFactory(beanFactory);
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}

从方法的整体流程可以看出,不管当前是不是存在一个 BeanFactory ,这里都会创建一个新的,并进行初始化,我们来逐行分析代码。

销毁已有的 BeanFactory

一开始,会判断当前是否存在一个 BeanFactory,如果有的话,就销毁其中的 Bean,并关闭 BeanFactory。这部分逻辑对应方法体开头的 if 语句块。因为我们分析的是 Spring 容器第一次创建时候的流程,而且之前并没有 BeanFactory 创建的逻辑,所以,目前为止,并不存在一个 BeanFactory,if 语句中的逻辑不会被执行。

实例化新的 BeanFactory

接下来就是 try 语句块中的部分。

首先,执行了 createBeanFactory 方法,创建了一个 BeanFactory。这里的代码也很简单:

protected DefaultListableBeanFactory createBeanFactory() {
   return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

获取到 parent 后,调用构造方法,创建了一个 DefaultListableBeanFactory 的实例并返回。

DefaultListableBeanFactory 这个类型是第一次见到,我们可以大致看一下它的继承关系:

这里的接口实现关系错综复杂,可以先看看留个印象。值得一提的是,它的子类 XmlBeanFactory 是 Spring 中非常重要的一个类,是 Spring 的初级容器。如果使用 XML 配置文件来直接创建 BeanFactory 使用的就是 XmlBeanFactory ,不过现在这个类已经被标记了 @Deprecated。

言归正传,回到 refreshBeanFactory 方法中来。创建好 BeanFactory 后,通过 beanFactory.setSerializationId(getId()) 给了它一个 Id,序列化和反序列化的时候用。

对 BeanFactory 进行自定义

接下来,customizeBeanFactory(beanFactory) 执行了 ApplicationContext 对内部的 BeanFactory 的自定义。

protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
   if (this.allowBeanDefinitionOverriding != null) {
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   if (this.allowCircularReferences != null) {
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
   }
}

 

这里通过给 beanFactory 的成员变量赋值,做了两件事:

  • 允许相同名称的 BeanDefinition 在容器中被覆盖
  • 允许多个 Bean 之间存在循环依赖

这两点涉及到了 BeanDefinition 和 Bean 初始化的流程,根据容器初始化的整体流程(可以参考:Spring 源码阅读:ApplicationContext 初始化 Spring 容器 ),在之后的代码中应该会遇到。

加载 BeanDefinition

最后一个方法调用,loadBeanDefinitions(beanFactory); 执行了 BeanDefinition 的加载。这里的实现逻辑可以在 AbstractXmlApplicationContext 中找到:

 /**
* Loads the bean definitions via an XmlBeanDefinitionReader.
*  @see  org.springframework.beans.factory.xml.XmlBeanDefinitionReader
*  @see  #initBeanDefinitionReader
*  @see  #loadBeanDefinitions
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // Create a new XmlBeanDefinitionReader for the given BeanFactory.
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

   // Configure the bean definition reader with this context's
   // resource loading environment.
   beanDefinitionReader.setEnvironment(this.getEnvironment());
   beanDefinitionReader.setResourceLoader(this);
   beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

   // Allow a subclass to provide custom initialization of the reader,
   // then proceed with actually loading the bean definitions.
   initBeanDefinitionReader(beanDefinitionReader);
   loadBeanDefinitions(beanDefinitionReader);
}

在这个方法中,首先创建了一个 XmlBeanDefinitionReader 的实例,并对其进行了配置。从它的名字可以知道,这个类用来读取 XML 中的 Bean 定义。

创建好之后,末尾调用了两个方法,我们先看 initBeanDefinitionReader 的源码:

protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader) {
   reader.setValidating(this.validating);
}

方法名告诉我们方法的作用是对 XmlBeanDefinitionReader 进行初始化,这里只是设置了是否对 XML 文件进行验证(默认值是 true),其余什么也没干。我们还注意到,这个方法是 protected 修饰的,因此可以断定,这里是 Spring 留给我们的一个扩展点。我们可以通过重写这个方法,关闭 XML 验证、自定义 XML 的解析器,或者执行其他的一些设置。

最后将 beanDefinitionReader 作为参数,调用了另外一个 loadBeanDefinitions 方法。源码如下:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   Resource[] configResources = getConfigResources();
   if (configResources != null) {
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
      reader.loadBeanDefinitions(configLocations);
   }
}

在这里,分别将 configResources 和 configLocations 作为参数,执行了 reader 的 loadBeanDefinitions 方法。不过,getConfigResources 这个方法直接返回了 null,因此,这里的逻辑就是,根据我们创建 ClassPathXmlApplicationContext 时提供的配置文件路径,进行 BeanDefinition 的加载。

完成初始化并赋值

方法的末尾,通过 this.beanFactory = beanFactory; 将之前创建并初始化好的 BeanFactory 赋值给 beanFactory 成员变量。

getBeanFactory 方法

最后我们在回到最开始的 obtainFreshBeanFactory 方法,看一下里面调用的第二个方法 getBeanFactory() 的源码,实现逻辑在 AbstractRefreshableApplicationContext 类中:

@Override
public final ConfigurableListableBeanFactory getBeanFactory() {
   synchronized (this.beanFactoryMonitor) {
      if (this.beanFactory == null) {
         throw new IllegalStateException("BeanFactory not initialized or already closed - " +
               "call 'refresh' before accessing beans via the ApplicationContext");
      }
      return this.beanFactory;
   }
}

这里其实就是把 refreshBeanFactory 方法创建并初始化的 BeanFactory 获取到并返回。

Obsidian跨设备同步实战:阿里云OSS与Remotely Save插件配置指南 本文详细介绍了如何利用阿里云OSS对象存储与Remotely Save插件,为Obsidian笔记软件搭建一个低成本、高可靠性的私有化多端同步方案。从创建OSS Bucket、配置CORS规则、生成子账户密钥,到插件安装与多设备同步策略,提供了完整的实战配置指南,有效解决Obsidian用户的跨设备同步痛点。 阅读详情

相关推荐

(UE5 5.2)HISM Mobile DrawInstance在渲染层的实现浅分析

在 (UE4 4.27) UHierarchicalInstancedStaticMesh(HISM)原理分析 这篇博客大致介绍HISM组件从游戏线程到渲染线程的重建KD-Tree和剔除并提交DrawCall逻辑,但是没有分析渲染层的大致数据结构和实现. 可以看出FHierarchicalStaticMeshSceneProxy 实际存储Instance数组数据来自于FInstancedStaticMeshSceneProxy FHierarchicalStaticMeshSceneProxy只是以FClu

qq_29523119的博客 2725

Spring源码学习第二节

IOC容器初始化过程 发起是上一节课,的refresh()来启动的。启动会进行,BeanDefinition的Resouce定位、载入和注册三个基本过程。(spring把三个过程分开了,在不同的模块完成,然后组合起来,这样就可以更加灵活的剪裁和扩展)。 1.Resource定位,它由ResourceLoader通过统一的Resource接口完成。 2.BeanDefinition的载

lvhao2813的博客 235

RK3588上rknn_toolkit_lite2报错解决:手把手教你更新librknnrt.so的正确姿势

本文针对在RK3588平台上使用rknn_toolkit_lite2时遇到的“Invalid RKNN model version”等常见错误,提供了完整的诊断与解决方案。文章深入剖析了RKNN生态系统各组件(如librknnrt.so、RKNN Server)版本不兼容的根源,并手把手指导如何安全、正确地更新librknnrt.so运行时库,确保AI模型在RK3588 NPU上实现高效推理。

weixin_29189003的博客 521

Spring IOC:obtainFreshBeanFactory调用链

obtainFreshBeanFactory 方法会解析所有 Spring 配置文件(即我们在前文中介绍的contextConfigLocation配置),将所有 Spring 配置文件中的 bean 定义封装成 BeanDefinition,加载到 BeanFactory 中。

CRUD工程师 545

(nginx) nginx5 nginx https部署实战

综上所述,相比 HTTP 协议,HTTPS 协议增加了很多握手、加密解密等流程,虽然过程很复杂,但其可以保证数据传输的安全。所以在这个互联网膨胀的时代,其中隐藏着各种看不见的危机,为了保证数据的安全,维护网络稳定,建议大家多多推广HTTPS。SSL 证书费用很高,以及其在服务器上的部署、更新维护非常繁琐HTTPS 降低用户访问速度(多次握手)网站改用HTTPS 以后,由HTTP 跳转到 HTTPS 的方式增加了用户访问耗时(多数网站采用302跳转)

weixin_50382197的博客 1505

【全新官方接口】php检测微信域名拦截,检测微信域名被封

你的域名在微信被拦截的3种常见情况 1、域名因违规或有风险被拦截(红色拦截) 2、类似taobao.com,douyin.com这种的恶意竞争式拦截,淘宝、抖音等微信的竞争对手一般都是白色拦截(白色拦截) 3、有一个中间页的拦截,需要多次点击按钮才可以跳转到你的域名的,多是一些新型域名后缀,例如.top .xyz .link后缀,这种情况,备案后可以解决(备案拦截) 通过php get_headers()函数就可以分析到结果 这个下标为6是一个URL,在微信访问后正是这个讨厌的页面! 如果切换为

TANKING,开源开发者! 2877

BeanFactory初始化

先从上图红点debug进入代码configLoacations 指的是你的资源文件位置,此处指的就是classPath下的applicationContext.xmlrefresh默认为true, parent我们没传为空。我们顺便来看看classPathxmlApplicationContext的继承关系setConfiglocations是classPathXmlApplicationCont...

mmalan的博客 1918

视频生成工具本地部署完全指南:Seedance能装吗?有哪些开源替代?

本文系统介绍了视频生成模型的本地部署方案,分为三个部分:1)Seedance 2.0的混合部署模式,其开源组件可本地集成但核心功能需调用API;2)完全开源替代方案对比,包括LTX-2、Wan 2.1等模型的硬件需求与特点;3)详细部署指南,以ComfyUI+Wan 2.1为例,涵盖软件准备、模型整合、参数调优等步骤,并提供了显存优化和多GPU配置技巧。文章为需要离线视频生成能力的用户提供了完整技术路径。

小明的博客 1万+

BeanFactory 初始化方法及其标准顺序

源码摘抄 package org.springframework.beans.factory; import org.springframework.beans.BeansException; import org.springframework.core.ResolvableType; import org.springframework.lang.Nullable; /** * 用于访问Spring bean容器的根接口。 * * 这是bean容器的基本客户端视图。 其他接口,例如{@link

萧曳丶 646

39-Halcon-- fit_primitives_object_model_3d函数功能(从3D数据中提取几何基元)

Halcon算子fit_primitives_object_model_3d工业应用精要 该算子专为3D几何特征提取设计,支持平面、球体、圆柱等基元拟合。核心优势: 参数化输出:返回几何元素的数学参数(如平面方程、球心半径) 智能控制:通过max_dist、min_size等参数调节拟合精度 工业场景适配:针对薄壁件、孔系等提供专用优化方案 典型应用流程: 数据预处理(点云降噪/采样) 基元类型与参数设置 多阶段拟合(先平面后圆柱) 几何精度验证 误差控制在0.1%-1.2%范围内(视点云密度而定),适用于

weixin_45590420的博客 1162

YOLO11改进 - 卷积Conv | DEGConv(方向引导边缘门控卷积) : 空间分块、方向先验、轻量边缘增强

本文介绍了方向引导边缘门控卷积(DEGConv),一种专为增强边缘敏感度与方向感知能力设计的轻量级模块。该方法通过 Sobel 算子生成方向嵌入,结合条纹卷积提取水平与垂直边缘特征,并利用门控机制动态抑制背景噪声,从而精准捕捉细粒度结构。我们将 DEGConv 成功集成进 YOLO11,在 Backbone 的 SPPF 后及 Neck 的 P3、P4 分支中引入该模块以优化特征提取。实验证明,集成 DEGConv 的 YOLO11 在检测任务中表现优异,有效提升了模型对复杂边缘与方向特征的建模能力。

魔改工程师的博客 678

初学Spring源码3.2:obtainFreshBeanFactory()

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() 这个方法一共做了两件事: 创建一个BeanFactory(DefaultListableBeanFactory类型),并将其设置为当前应用上下文的实例变量 创建了一个或多个BeanDefinitionReader(设置了Environment和ResourceLoader等参数),将在BeanDefinition信息到BeanFactory中 /** * Tel

qq_34069839的博客 338

实现两端固支梁热力耦合的有限元分析

在本文中,我们将使用Matlab实现两端固支梁的热力耦合有限元分析。我们假设梁的材料是均匀的,梁的截面积为1,长度为1,两端固支,且受到均匀分布的热荷载。接下来,我们需要组装全局刚度矩阵和热传导矩阵。对于两个相邻的元素,它们共享一个节点,因此需要使用连接矩阵将局部矩阵组装成全局矩阵。接下来,我们需要定义元素刚度矩阵和热传导矩阵。然后,我们需要定义载荷向量。然后,我们需要定义边界条件。在这个例子中,梁的两端固支,因此我们需要将两端节点的位移限制为0。最后,我们需要解决线性方程组,得到节点的位移和温度分布。

CyberSparkZ的博客 396

Spring源码阅读之准备篇

引言“目前,在以Java语言主导的项目中,我们会使用各种各样的框架来快速搭建应用,尤其在Java web项目中,我们会经常见到Spring的身影,大部分人只知道怎么使用它,但是不知道它...

ShiLuoHeroKing的博客 326

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Spring源码阅读-BeanFactory子接口AutowireCapableBeanFactory 注释翻译

package org.springframework.beans.factory.config;import java.util.Set;import org.springframework.beans.BeansException; import org.springframework.beans.TypeConverter; import org.springframework.beans.f

iycynna_123的博客 3905

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

spring源码深度解析---容器的功能扩展(下)

spring源码深度解析—容器的功能扩展(下) 接容器的功能扩展(上) 6. BeanFactory的后处理 BeanFactory作为spring中容器功能的基础,用于存放所有已经加载的bean,为例保证程序上的高可扩展性,spring针对BeanFactory做了大量的扩展,比如我们熟悉的PostProcessor就是在这里实现的。接下来我们就深入分析下BeanFactory后处理 ...

渔潭的博客 507

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

理解Spring:IOC的原理及手动实现

本文转自:https://juejin.im/post/5c11b1e06fb9a04a0d56b787 Spring系列之IOC的原理及手动实现 目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 Spring系列之AOP的原理及手动实现 Spring系列之手写注解与配置文件的解析 Spring系列之手写一个SpringMVC 导语 Sprin...

lixiaoxiong的专栏 242

理解 Spring:IOC 的原理及手动实现

点击上方“Java基基”,选择“设为星标”做积极的人,而不是积极废人!源码精品专栏原创 | Java 2020超神之路,很肝~中文详细注释的开源项目RPC 框架 Dubbo 源码解析网...

weixin_44421461的博客 183

Spring读源码系列05----bean的加载---中

Spring读源码系列05----bean的加载---下循环依赖什么是循环依赖spring是如何解决循环依赖的1.构造器循环依赖2.setter循环依赖3.prototype范围的依赖处理创建BeanAbstractAutowireCapableBeanFactory#createBean—创建bean前的准备AbstractAutowireCapableBeanFactory#doCreateBean—真正创建beanAbstractAutowireCapableBeanFactory#createBea

m0_53157173的博客 877

肝了30天总结,史上最全面透彻的Spring核心原理分析和27道高频面试题

1 什么是Spring框架,Spring框架有哪些主要模块 Spring框架是一个为Java应用程序开发提供综合、广泛的基础性支持的Java平台。Spring帮助开发者解决了开发中基础性的问题,使得开发人员可以专注于应用程序的开发。Spring框架本身也是按照设计模式精心打造的,这使得我们可以在开发环境中安心地集成Spring框架,不必担心Spring是如何在后台工作的。主要模块内容介绍可以参考之前章节的介绍。 2 使用Spring框架能带来哪些好处 下面列举了一些使用Spring框架带来的主要好处。

Tom弹架构 580

工作中使用到的单词(软件开发)

1.エイリアス   alias 别名 powershell使用 get-help 命令时,会得到与此命令 相关(别名)的命令 2.プロキシ proxy 代 理 3.プロモート   promote 促进,提升   开发的系统新功能上线发布,有时会使用到这个词,比如 STプロモート 还有使用リリース这个词的。比如STリリース。个人认为两者含义相同。 4.見逃し み................................................................

sun0322 6万+

Spring IOC容器启动源码分析文字版

Spring容器的refresh()【创建刷新】;1、prepareRefresh()刷新前的预处理;    1)、initPropertySources()初始化一些属性设置;子类自定义个性化的属性设置方法;    2)、getEnvironment().validateRequiredProperties();检验属性的合法等    3)、earlyApplicationEvents= new...

仲翎逸仙 837

Spring启动流程(二)——获取BeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName(

weixin_38910645的博客 1415

Spring--BeanFactory--使用/原理/详解

本文介绍Spring里的BeanFactory。包括:BeanFactory 和 FactoryBean的区别,ApplicationContext的委托。

IT利刃出鞘的博客 4039

Spring源码系列之——BeanFactory和ApplicationContext

Hello~大家好,只做技术交流分享~若大佬路过,请多指教~。该文章为spring源码系列文章,讲解的是beanFactory和ApplicationContext的区别,以及它们分别做了什么,娓娓道来~

weixin_43398098的博客 1281
上一篇: SpringBoot中使用注解来实现 Redis 分布式锁
下一篇: 试试使用Spring Event组合@Async注解,轻松实现代码的解耦和异步
java_lujj
博客等级 码龄4年 18粉丝 152原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值