【spring源码解析】bean的一生

彻底弄懂Spring中Bean的解析、创建和使用 Spring加载Bean、实例化Bean、获取Bean流程 本文旨在通过分析源码的方式,来剖析Spring加载Bean、实例化Bean、获取Bean的流程,部分核心内容会在源码中说明。内容比较枯燥,慎入! 第一步,启动一个Spring项目 Spring启动入口 从官方文档中我们可以获取到下面这种Spring的启动方式。 我们传入一个text.xml文件 ApplicationContext context = new ClassPathXmlApplicationContext("classpa 阅读详情

探究源码

我们进入调试查看源码

由于源码非常之多,这里就只记录执行过程中做的一些事情

工厂源码

加载过程

新建对象找到spring对象的位置,找到配置文件的位置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nXs6Lt16-1633886743882)(spring.assets/image-20211010200357454.png)]

之后判断refresh,开始刷新

refresh

spring最核心的方法,refresh都做了什么呢?

首先就是准备刷新:

  • 记录毫秒值,是不是关闭,选择启动
  • 日志打印,给子类做一些默认的事情,校验一些属性,有没有子类复写的一些属性,如果有就执行,没有继续往下走
  • 判断,之后将应用的一些初始化事件放到集合里

准备好刷新之后,

准备bean工厂

  • 添加bean的加载器,spring表达式的解析器,属性编辑器
  • 设置一些必要的后置处理器
  • 忽略一些接口
  • 将bean的信息注册,加入资源解析器,注册事件发布,上下文对象
  • 获取一些系统属性判断加载,如:jre的名字,user.home的路径,语言环境等等
  • 之后返回工厂对象

工厂对象创建

  • 判断是否有工厂,没有的话创建
  • 创建一个默认的工厂返回。默认创建的工厂包含了很多的默认信息
  • 之后给bean工厂按满足的条件赋值
  • 解析描述信息类,加载描述信息,如果是xml那么就是解析xml
  • 将解析完的类描述i信息,复制到Bean工厂里

到这里工厂的创建就完成了

后置处理器

注册全部的后置处理器,一般来说。有多少注入的类就有多少后置处理器

执行流程

  • 遍历,有多少后置处理器,创建集合,循环判断所有处理器,是否属于当前接口,之后将所有的后置处理器放在对应的集合里,给处理器id
    • 优先级
    • 内部的
    • 等等
  • 之后,给优先级集合中的处理器排序,有序的注册
  • 之后判断其他的处理器的集合
  • 最后判断没有优先级的集合,最终全部注册到容器中

国际化和事件监听器

  • 判断是否有国际化,如果包含,加入到工厂里,输出日志调用
  • 事件监听器也是,判断是否有,如果保函就从里面拿出来,日志输出,如果不保函就创建一个事件监听器,

注册事件监听器

  • 默认是没有,如果有,拿到全部的默认监听器
  • 设置临时类加载器
  • 判断事件监听器是否是空的,如果不是就全都拿来发出去,

创建bean

创建单例对象,不能是懒加载的

  • 首先先寻找工厂里有没有值解析器,如果没有就创建一个新的值解析器
  • 查看冻结配置,为true就将存放再配置文件的bean组件们,转换成字符串数组
  • 根据名字从集合中拿出来,遍历创建对象,根据名字拿到bean的信息,满足三个条件才往后走
    • 不能是抽象的
    • 必须是单例的
    • 不能是懒加载的
  • 如果不满足,那就是工厂创建
  • 从缓存拿到单例对象,要是没有就去看是否满足判断条件,查看是否多次创建对象,之后查看bean工厂,
  • 标记当前对象,正在创建,之后放到set集合中,表示最后一次创建,
  • 检查当前bean的信息,查看是否需要其他的依赖来创建,判断是不是单例,
  • 用集合存放对象和一个构造工厂
  • 有一个实例resolveBeforeInstantiation的创建,通过后置处理器,来实现创建代理对象,这一步就是有可能创建对象的,当我们要用aop的时候就用这个方法拿到代理对象.
  • 如果没有就创建对象,传入对象信息,再次判断是不是单例的,之后创建单例对象,
  • 之后判断对象,看是不是需要必须指定的构造方法,默认是空参数构造方法,
  • 之后拿到bean实例,判断是否为空,判断接口类型,检查对象,拿到无参数构造方法
  • 创建对象,用反射标记当前的构造方法,用无参构造方法构建实例,到这里bean对象就创建成功了
  • 这里的bean对象是最初始的状态,包装给BeanWapper做一个初始化,到这里空的对象就创建好了。
  • 之后调用后置处理器,回调如果组件里有就调后置处理器,最后到了这里开始对空对象赋值
  • 之后再次拿到单例对象,之后就去拿到赋值,返回创建的对象
  • 通过单例工厂创建出对象,将新建的对象放入单例对象集合中
  • 移除用来检查循环依赖的单例工厂,确认注册对象成功,set的不会存放重复值的,所以就一个
  • 经过大量判断之后返回对象实例

完成刷新,发布事件消息

  • 初始化包含的处理器,如果有就get拿进去,如果没有那就创建
  • 之后刷新后置处理器
  • 发送创建事件信息,告诉spring初始化完成了
  • 之后注册上下文拿到当前的名字。如果不等于空那就加入到applicationContext中,至此完成

循环依赖问题

我们创建两个对象,

UserA的构造方法调用UserB对象

循环依赖,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ktL8AImX-1633886743883)(spring.assets/image-20211011010440079.png)]

这个是调试断点进入到有参构造方法

  • 进入之后,可以看到需要参数要引用到UserB,UserB也是个bean所以spring要去创建userB所以userB就需要参数创建userA导致一直循环创建
  • 当spring发现UserB还在创建userA的时候spring就会抛出异常为什么再次创建的时候就异常了呢?
  • 因为存放获取bean的是set之前创建bean的时候我们有提到,只要创建bean就会放在里,有个判断,set是没有重复值的只要判断没通过,就证明之前有正在创建的对象·,于是抛出异常
  • 通过缓存的要创建的bean来判断是否重复引用bean,解决循环依赖问题

如何解决呢?

  • 我们用构造方法调用引用其他类,创建的时候,一直在重复的创建对象
  • 我们只需要,用属性来声明一个应用对象,需要的时候调用,使用的完就销毁
  • 就不会存在循环依赖的问题了

总结

spring框架的精妙之处,太多值得我们学习,这次的bean的一生只是将思想和大致过程讲解,还有很多需要结合场景的细节,需要我们自己的去探索,不断地深究才可以让自己的技术变得强大

Spring源码之bean的解析obtainFreshBeanFactory方法解读 目录前言 前言 一直以来,只是知道 spring 会解析所有的配置文件(通常我们会放在 resources 目录下),然后将从配置文件中解析到的 bean 定义封装成 BeanDefinition,加载到 IOC 容器中。而不知道其内部是如何解析,执行的,本篇文章将予以揭秘 ... 阅读详情

相关推荐

Spring之Bean生命周期源码解析(一)

Spring之Bean生命周期源码解析(一) Bean生命周期流程 Bean包扫描底层流程 MetadataReader 合并BeanDefinition 加载类 什么是Bean的生命周期 Bean的生命周期就是指:在Spring中,一个Bean是如何生成的,如何销毁的 Bean生命周期流程图 Bean的生命周期: 启动ApplicationContext 创建BeanFactory 初始化BeanFactory 在BeanFactory后置处理:在这里会进行包扫描,找.

a6636656的博客 721

深度解析 Spring 源码:从BeanDefinition源码探索Bean的本质

本文深入解析Spring框架的核心组件之一,即BeanDefinition,探索Bean的本质。首先介绍了BeanDefinition的概念和作用,它是Spring中管理Bean配置元数据的接口,定义了Bean的各种属性和行为。接着,分析了BeanDefinition的实现类以及其重要属性,如Bean的类名、作用域、构造函数、依赖关系等。通过深入研究BeanDefinition的源码,揭示了Spring是如何管理和创建Bean实例的过程。

忆~遂愿的博客 5075

Spring源码解析 - Bean的创建详解!

在上期文章中,我们探讨了Spring IOC 容器的初始化流程,从容器的启动到 BeanFactory 的创建,逐步揭开了 Spring 强大功能的神秘面纱。通过深入研究,我们了解了 Spring 是如何通过和等机制,为开发者提供灵活而强大的依赖注入支持。然而,IOC 容器的核心功能并不仅仅局限于容器的初始化,更为关键的是容器如何创建、管理和销毁 Bean。在本期文章中,我们将聚焦于Spring 中 Bean 的创建流程,从源码层面深度解析其背后的逻辑和机制。

喵手的博客 750

Spring Bean的相关源码分析

本文主要分析了Spring的创建过程、bean的生命周期、bean的创建过程、beanDefinition的创建过程、Spring Boot的启动过程。 另外还基于以上内容的探讨分析了一些常见Spring的功能实现原理,比如Spring Boot是如何扫描自动配置类的

weixin_55658418的博客 504

matlab液体湿润模拟,【水文模型】01 三水源新安江模型

目录一、概述1.1 流域概况1.2 产流方式论证1.3 设计基本任务1.4 设计原始资料二、新安江模型2.1 流域划分2.2 产汇流计算2.2.1 蒸散发计算2.2.2 产流计算2.2.3 水源划分2.2.4 汇流计算2.3 模型参数2.3.1 参数物理意义2.3.2 参数率定结果2.4 模拟结果2.4.1 精度统计表2.4.2 计算与实测流量过程线比较三、精度统计与误差分析3.1 精度统计3.2...

weixin_34173656的博客 5327

机器学习 线性回归 头歌实训

第1关:简单线性回归与多元线性回归 第2关:线性回归的正规方程解 第3关:衡量线性回归的性能指标 第4关:scikit-learn线性回归实践 - 波斯顿房价预测

weixin_57270536的博客 1万+

Spring原理:Bean详解(含源码分析)

介绍了Bean的创建:包含使用类注释、以及使用方法构建;介绍了Bean 的使用与依赖注入;介绍了Bean 在 Spring 以及Spring web MVC 中的作用域

m0_74209411的博客 1596

简要介绍 | 两阶段点云目标检测:理论与实践

目标检测是计算机视觉中的一个重要任务,其目的是识别和定位图像中的物体。对于二维图像,这已经有许多有效的方法。然而,对于三维数据(如由LiDAR生成的点云数据),目标检测则更为复杂。

NLOS的博客 1307

【spring】创建Bean的方法:createBean源码分析

深入了解Bean是如何创建的,在创建 过程中需要维护什么信息!

qq_35436158的博客 661

计算机组成原理(第三版)唐朔飞-第七章指令系统-课后习题

机器字长是指CPU一次能处理数据的位数通常与CPU的寄存器位数有关。指令字长是指机器指令中二进制代码的总位数。存储字长是指存储单元中存放二进制代码的总位数。三者可以相等也可以不等视不同机器而定。答:OP(4位)A1(6位)A_1(6位)A1​(6位)A2(6位)A_2(6位)A2​(6位)设二地址指令格式为该指令系统的基本格式,4位操作码共有16种编码,其中13种用来定义二地址指令,还剩3种可用作扩展标志。一地址指令条数=3∗26=192。

weixin_45735391的博客 7万+

Qt实现窗口自适应分辨率大小

如果希望窗口大小始终保持与屏幕分辨率一致,可以将上述代码放在窗口的resizeEvent()函数中。这样,每当窗口大小发生变化时,都会自动调用resizeEvent()函数,从而实现窗口大小的自适应调整。在Qt中,可以通过一些简单的方法实现窗口大小随分辨率变化而自适应调整。获取到当前屏幕的分辨率后,可以根据需要调整窗口的大小。无论在何种分辨率下运行应用程序,窗口都能够正确地自动调整大小,提供更好的用户体验。除了调整窗口大小,还可以考虑将窗口设置为最大化,以充分利用屏幕空间。步骤2:调整窗口大小。

FuJavascript的博客 3655

Spring实例化Bean源码解析

在上一篇文章中,我们说完了Spring环境初始化的过程,接下来讲一下Bean的实例化过程。这篇文章中,暂时不对Bean循环依赖的情况进行分析,因为比较复杂,会放在后面单独的文章中进行分析。 接着从上篇文章中没有讲完的AnnotationConfigApplicationContext类的refresh方法开始分析,从下面这条语句开始: // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitializa

1149

基于 STM32 的智能水表流量计设计与实现 —— 数据采集与远程传输

本文设计的基于 STM32 的智能水表流量计通过霍尔传感器实现流量采集,结合 STM32 的处理能力完成数据计算、存储与远程传输,具备计量精准、功耗低、可远程监控等特点。未来可优化方向:引入低功耗模式延长电池寿命,增加水质检测模块实现多参数监测,提升水务管理智能化水平。

weixin_42300449的博客 1028

Spring源码解析(三):bean容器刷新

上一讲Spring源码解析(二):bean容器的创建、默认后置处理器、扫描包路径bean主要是刷新上下文的准备工作进入refresh();方法,此方法定义在注解上下文父类AbstractApplicationContext注解配置上下文只是它的子类之一,还有xml上下和web上下文等// 1、刷新前预处理 prepareRefresh();

从基础到源码解析的学习记录 1554

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Spring 源码解读第七弹!bean 标签的解析

Spring 源码解读继续。 本文是 Spring 系列第八篇,如果小伙伴们还没阅读过本系列前面的文章,建议先看看,这有助于更好的理解本文。 Spring 源码解读计划 Spring 源码第一篇开整!配置文件是怎么加载的? Spring 源码第二弹!XML 文件解析流程 Spring 源码第三弹!EntityResolver 是个什么鬼? Spring 源码第四弹!深入理解 BeanDefinition 手把手教你搭建 Spring 源码分析环境 Spring 源码第六弹!松哥和大家聊聊容器的始祖 Def

江南一点雨的专栏 5188

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Spring Bean 的实例化过程源码解析

1 工程概述 1.1 pom <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.tar

qq_34125999的博客 1万+

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Spring源码解析(四):单例bean的创建流程

接下来说下Spring源码解析(三):bean容器的刷新中最重要的实例化剩余的非懒加载bean进入beanFactory.preInstantiateSingletons();方法} // 创建beanDefinitionNames的副本beanNames用于后续的遍历,以允许init等方法注册新的bean定义 List < String > beanNames = new ArrayList < >(this . beanDefinitionNames);

从基础到源码解析的学习记录 1259

Spring深度学习:Bean生命周期及源码解析

本文小豪将带大家深度学习Spring Bean相关知识,包括Bean的生命周期及Bean创建过程的底层源码,学习过程中不仅仅是了解Spring Bean的工作原理,更重要的是学会理解框架的底层逻辑,从而提升我们的思维能力。

Code豪客 2039

spring源码解析流程,一步一步在源码加注释带你了解bean的加载过程

spring 前述:spring源码环境搭建以及源码下载在文章后方有链接,可自行参考搭建,这里只是对加载过程做一个解析,spring全家桶远不止这些东东,感兴趣的小伙伴可以去官网看一下,本文将以源码加注释的方式进行过程解析,带你了解spring中bean到底是如何一步步加载完成 了解重点:bean的生命周期、加载过程 最终目的:学习spring源码短期内不对对你的技术有太大提升,可能只是了解到漂亮的代码是如何写出来,为何别人写代码就不是简单的接口加上无限的if-else,所以加强基础知识的学习、多去思考如何

F957614265的博客 3906

Spring源码解析之bean的创建

阅读须知 研究了半天markdown也没发现怎么为代码块中的重点代码做特殊标记,所以这里使用//单行注释做代码的简单注释,而/**/多行注释的代码注释的同时会做深入分析,同时为了避免篇幅过长,删掉了Spring原来的注释和空行,建议配合Spring源代码进行阅读,本文对应的Spring源码的版本为4.3.8。 正文 之前我们都是在围绕 ApplicationContext applic

0xZzzz的博客 9171

spring源码深度解析_Spring的底层源码解析

Spring 运行原理 : Spring 启动时读取应用程序提供的Bean配置信息,并在Spring容器中生成一份相应的 Bean 配置注册表,然后根据这张注册表实例化 Bean,装配好 Bean 之间的依赖关系,为上 层应用提供准备就绪的运行环境。 然后spring容器会定义一个Bean注册表,之后会根据注册表的信息,去加载到Bean实现类,实例化bean的实现类,在实例化的过程当中,完成一个...

weixin_39609483的博客 4330

Spring之Bean生命周期源码解析

实例化自动注入Aware对象初始化。

EverythingAtOnce的博客 1647

Spring源码分析之Bean的解析

前言 Spring源码分析是一个系列,源码是Spring 4.X,本系列主要分析Spring的代码执行流程,过于细节的内容将不会涉及太多,主要是为了理清Spring的执行流程,比如Bean的解析是如何进行的,解析完成之后是如何进行加载的等等,对于在Bean的解析过程中涉及的一些细节很大可能不会在本系列的分析中找到,本系列的每一篇文章都是基于Spring源码的某条主要线索来进行,因为Spring的...

zcywell的专栏 1024

一个 Bean 就这样走完了它的一生之 Bean 的出生

一个 Spring 中的 Bean 的生命周期是怎样的,本文将从 Spring 源码的角度带你一步一步查看 Spring 中的 Bean 的生命周期的每个方法是什么时候调用的。

javadaysdaysup的博客 729
上一篇: 一键解决环境问题,容器化究竟带来什么好处?
下一篇: http基本概念
冷环渊
博客等级 码龄7年 1130粉丝 176原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷环渊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值