当前位置: 首页 > news >正文

Spring如何管理Bean的生命周期呢?

我们都知道,在面试的过程中,关于 Spring 的面试题,那是各种各样,很多时候就会问到关于 Spring的相关问题,比如 AOP ,IOC 等等,还有就是关于 Spring 是如何管理 Bean 的生命周期的相关问题,今天了不起就来和大家一起看看 Spring 是如何管理 Bean 的生命周期的。

源码分析

BeanFactory

其实我们对于这个 Spring 管理 Bean 的生命周期有时候并不需要我们去大篇幅的去背诵某块的内容,我们需要的就是学会看源代码,比如源代码中的注释部分,当我们看到这注释部分的时候,很大程度上能够帮助我们理解源码的含义。

BeanFactory是Spring框架中的一个接口,它是一个工厂类,用来创建和管理Spring中的Bean对象。

我们看源码中的注释

* <p>Bean factory implementations should support the standard bean lifecycle interfaces* as far as possible. The full set of initialization methods and their standard order is:

这句话直接翻译就是 Bean Factory 实现类应该尽可能的支持标准的生命周期接口。注释的下半段内容,就是描述的 Bean 生命周期的相关内容了。所以源码里面的注释需要我们及时的去看一下,虽然都是纯英文的,但是能读出个大概得内容,再去看源码的话,至少知道它是干嘛的方法。

Bean 的生命周期

我们在了解他如何管理的时候,我们得先知道这个 Bean 的生命周期都有哪几个阶段,知道了阶段,我们再来看它的实现。

我们先总结:

Bean 的生命周期可以总结为如下的几个阶段,

1. Bean的实例化阶段

2. Bean的设置属性阶段

3. Bean的 初始化阶段

4. Bean的销毁阶段

也有些人会细分实例化阶段,就是把实例化拆分成两部分,第一部分是注册阶段,第二部分是实例化阶段,其实区别不大。

Bean实例化阶段

在Spring框架中,Bean的实例化是一个核心过程,它涉及了多个步骤以确保Bean能够正确地被创建并注入到应用上下文中。

Bean定义注册:

  • 首先,你需要在Spring的配置文件(如XML配置文件或Java配置类)中定义Bean。这包括指定Bean的类名、作用域、初始化方法、销毁方法以及可能的依赖关系等。

  • Spring容器会读取这些配置,并将Bean定义信息存储在其内部的数据结构中,通常是BeanDefinition对象。

实例化前的准备:

  • 在实例化Bean之前,Spring会进行一些准备工作,如解析Bean定义中的属性、检查依赖关系等。

  • 如果Bean定义中引用了其他Bean,Spring会尝试先解析并实例化这些依赖Bean。

实例化:

  • 实例化是创建Bean对象的过程。Spring提供了多种实例化Bean的方式:

    • 构造器实例化:通过调用Bean的构造方法来创建实例。你可以在配置文件中指定要使用的构造方法,并提供相应的参数。

    • 静态工厂方法实例化:通过调用静态工厂方法来创建Bean实例。你需要在配置文件中指定工厂类的类名和工厂方法的名称。

    • 实例工厂方法实例化:首先实例化一个工厂Bean,然后调用该工厂Bean的某个非静态方法来创建目标Bean实例。

    • 默认构造器实例化:如果Bean定义中没有指定其他实例化方式,并且Bean类有一个无参构造器,那么Spring将使用默认构造器来实例化Bean。

  • 实例化完成后,你得到的是一个原始的对象,它还没有进行任何属性注入或初始化。

属性注入:

  • 在Bean实例化之后,Spring会进行属性注入(也称为依赖注入)。这包括将Bean定义中指定的属性值或对其他Bean的引用注入到Bean的相应属性中。

  • Spring支持多种属性注入方式,如基于字段的注入、基于setter方法的注入和基于构造器的注入等。

BeanPostProcessor处理:

在Bean的属性注入完成后,但Bean的初始化方法执行之前,Spring会调用已注册的BeanPostProcessor接口的postProcessBeforeInitialization方法。这是一个可选的步骤,你可以通过实现该接口并注册相应的BeanPostProcessor来在Bean初始化前后执行自定义的逻辑。

初始化:

  • 接下来,Spring会调用Bean定义中指定的初始化方法(如果有的话)。这通常是在Bean类中定义的某个方法,并用特定的注解(如@PostConstruct)或XML配置中的元素的init-method属性来指定。

  • 初始化方法是Bean在准备好接受请求之前进行必要设置或执行特定任务的地方。

BeanPostProcessor再处理:

在Bean初始化方法执行之后,Spring会再次调用已注册的BeanPostProcessor接口的postProcessAfterInitialization方法。这是另一个可选的步骤,你可以在这里执行一些清理或后处理操作。

Bean就绪:

经过上述步骤后,Bean就已经被完全创建并初始化了。现在它可以被应用上下文中的其他组件使用或注入到其他Bean中。

到这里,我们的实例化就说完了,记下来看第二阶段。

Bean的设置属性阶段

Bean的设置属性阶段(也称为属性注入或依赖注入)是Bean生命周期中的一个重要环节。这个阶段发生在Spring容器创建Bean的实例之后,但在Bean被实际使用之前。

  • 当Spring容器创建一个Bean的实例后,它会检查该Bean是否有需要注入的属性。这些属性可能是其他的Bean、基本数据类型、集合、Map等。

  • Spring会查找与这些属性对应的配置信息(可能是XML中的标签、注解中的值或其他配置方式),并将它们注入到Bean的相应字段或setter方法中。

注入方式:

  • 字段注入:通过直接在字段上使用@Autowired或其他相关注解来实现。但请注意,字段注入在某些情况下可能导致测试困难或难以遵循良好的封装原则。

  • 构造函数注入:在构造函数参数上使用@Autowired或其他相关注解。这是推荐的方式之一,因为它确保了Bean在创建时就已经拥有所有必需的依赖项,并且这些依赖项是不可变的。

  • setter方法注入:在setter方法上使用@Autowired或其他相关注解。这种方式允许Bean在创建后的某个时间点接收其依赖项。

既然我们已经把这个属性设置完毕了,那么就要开始后进行初始化阶段了。

Bean 的初始化

  • Bean Aware接口回调

  • Bean初始化前操作

  • Bean初始化操作

  • Bean初始化后操作

  • Bean初始化完成操作

BeanAware接口回调

  private void invokeAwareMethods(final String beanName, final Object bean) {if (bean instanceof Aware) {if (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}if (bean instanceof BeanClassLoaderAware) {((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());}if (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}}

Bean初始化前操作

  @Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {result = beanProcessor.postProcessBeforeInitialization(result, beanName);if (result == null) {return result;}}return result;
}

Bean初始化操作

调用InitializingBean接口的afterPropertiesSet方法 调用定义bean的时候指定的初始化方法。

 public interface InitializingBean {/*** Invoked by the containing {@code BeanFactory} after it has set all bean properties* and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.* <p>This method allows the bean instance to perform validation of its overall* configuration and final initialization when all bean properties have been set.* @throws Exception in the event of misconfiguration (such as failure to set an* essential property) or if initialization fails for any other reason*/void afterPropertiesSet() throws Exception;} 

Bean初始化后阶段

 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}

Bean初始化完成操作

public interface SmartInitializingSingleton {/*** Invoked right at the end of the singleton pre-instantiation phase,* with a guarantee that all regular singleton beans have been created* already. {@link ListableBeanFactory#getBeansOfType} calls within* this method won't trigger accidental side effects during bootstrap.* <p><b>NOTE:</b> This callback won't be triggered for singleton beans* lazily initialized on demand after {@link BeanFactory} bootstrap,* and not for any other bean scope either. Carefully use it for beans* with the intended bootstrap semantics only.*/void afterSingletonsInstantiated();}

当我们完成了初始化之后,使用完成,最后 Bean 就要走到销毁阶段了。

Bean 的销毁

 @Overridepublic void destroyBean(Object existingBean) {new DisposableBeanAdapter(existingBean, getBeanPostProcessorCache().destructionAware, getAccessControlContext()).destroy();}

这里需要注意的是

  • 当容器关闭时,或者当单例 Bean 的作用域结束时,Spring 会销毁 Bean 的实例。

  • 对于非单例 Bean(如 prototype 作用域的 Bean),它们会在每次请求时创建,并在不再需要时由 Java 的垃圾回收机制销毁。

相关文章:

Spring如何管理Bean的生命周期呢?

我们都知道&#xff0c;在面试的过程中&#xff0c;关于 Spring 的面试题&#xff0c;那是各种各样&#xff0c;很多时候就会问到关于 Spring的相关问题&#xff0c;比如 AOP &#xff0c;IOC 等等&#xff0c;还有就是关于 Spring 是如何管理 Bean 的生命周期的相关问题&#…...

Java网络编程:UDP通信篇

目录 UDP协议 Java中的UDP通信 DatagramSocket DatagramPacket UDP客户端-服务端代码实现 UDP协议 对于UDP协议&#xff0c;这里简单做一下介绍&#xff1a; 在TCP/IP协议簇中&#xff0c;用户数据报协议&#xff08;UDP&#xff09;是传输层的一个主要协议之一&#xf…...

HTML+CSS+JS简易计算器

HTMLCSSJS简易计算器 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>简易计算器</t…...

STM32使用ST-LINK下载程序中需要注意的几点

使用keil5的ST-link下载界面 前提是ST-LINK已经连接好&#xff0c;&#xff08;下图中是没有连接ST-link设备&#xff09;&#xff0c;只是为了展示如何查看STlink设备是否连接的方式 下载前一定设置下载完成后自启动 这个虽然不是必须&#xff0c;但对立即看到新程序的现象…...

我和jetson-Nano的故事(12)——安装pytorch 以及 torchvision

在jetson nano中安装Anaconda、pytorch 以及 torchvision 1.Pytorch下载安装2.Torchvision安装 1.Pytorch下载安装 首先登录英伟达官网下载Pytorch安装包&#xff0c;这里以PyTorch v1.10.0为例 安装依赖库 sudo apt-get install libjpeg-dev zlib1g-dev libpython3-dev liba…...

「异步魔法:Python数据库交互的革命」(一)

Hi&#xff0c;我是阿佑&#xff0c;今天将和大家一块打开异步魔法的大门&#xff0c;进入Python异步编程的神秘领域&#xff0c;学习如何同时施展多个咒语而不需等待。了解asyncio的魔力&#xff0c;掌握Async SQLAlchemy和Tortoise-ORM的秘密&#xff0c;让你的数据库操作快如…...

探秘GPT-4o:从版本对比到技术能力的全面评价

随着人工智能技术的不断发展&#xff0c;自然语言处理领域的突破性技术——GPT&#xff08;Generative Pre-trained Transformer&#xff09;系列模型也在不断演进。最新一代的GPT-4o横空出世&#xff0c;引起了广泛的关注和讨论。在本文中&#xff0c;我们将对GPT-4o进行全面评…...

四川汇烁面试总结

自我介绍项目介绍、 目录 1.jdk和jre的区别&#xff1f; 2.一段代码的执行流程&#xff1f; 3.接口与抽象类的区别&#xff1f; 4.ArrayList与LinkList的区别&#xff1f; 5.对HashMap的理解? 6.常见的异常&#xff1f; 7.throw 和 throws 有什么区别&#xff1f; 8.…...

【小程序 按钮 表单 】

按钮 代码演示 xxx.wxml <view class"boss" hover-class"box"hover-start-time"2000"hover-stay-time"5000">测试文本<view hover-stop-propagation"true">子集</view><view>子集2</view>…...

高铁Wifi是如何接入的?

使用PC端的朋友&#xff0c;请将页面缩小到最小比例&#xff0c;阅读最佳&#xff01; 在飞驰的高铁上&#xff0c;除了窗外一闪而过的风景&#xff0c;你是否好奇过&#xff0c;高铁Wifi信号如何连接的呢&#xff1f; 远动的火车可不能连接光纤吧&#xff0c;难道是连接的卫星…...

gitlab之docker-compose汉化离线安装

目录 概述离线资源docker-compose结束 概述 gitlab可以去 hub 上拉取最新版本&#xff0c;在此我选择汉化 gitlab &#xff0c;版本 11.x 离线资源 想自制离线安装镜像&#xff0c;请稳步参考 docker镜像的导入导出 &#xff0c;无兴趣的直接使用在此提供离线资源 百度网盘(链…...

【算法】dd爱转转

✨题目链接&#xff1a; dd爱旋转 ✨题目描述 读入一个n∗n的矩阵&#xff0c;对于一个矩阵有以下两种操作 1:顺时针旋180 2:关于行镜像 如 变成 给出q个操作&#xff0c;输出操作完的矩阵 ✨输入描述: 第一行一个数n(1≤n≤1000)&#xff0c;表示矩阵大小 接下来n行&#xff…...

Python3 笔记:IDLE的几个基本设置

1、设置字体&#xff1a; Options > Configure IDLE > Fonts 2、设置文字颜色&#xff08;设置高亮&#xff09;&#xff1a; Options > Configure IDLE > Highlights 3、设置背景颜色&#xff1a; Options > Configure IDLE > Highlights 4、设置窗口&a…...

Mysql:存储过程练习

create table stu( id int(3) primary key auto_increment, name varchar(20) not null, grade float, gender char(2)); insert into stu(name,grade,gender) values(tom,60,男),(jack,70,男),(rose,90,女),(lucy,100,…...

详解Java ThreadLocal

个人博客 详解Java ThreadLocal | iwts’s blog Java ThreadLocal ThreadLocal提供了线程内存储变量的能力&#xff0c;这些变量不同之处在于每一个线程读取的变量是对应的互相独立的。通过get和set方法就可以得到当前线程对应的值。 TreadLocal存储模型 ThreadLocal的静态…...

Unable to parse response body for Response{requestLine=PUT

1 异常信息&#xff1a; Caused by: java.lang.RuntimeException: Unable to parse response body for Response{requestLinePUT /an_path_statistic_log/_doc/11?timeout1m HTTP/1.1, hosthttp://192.168.3.60:9200, responseHTTP/1.1 200 OK}at org.springframework.data.e…...

GitHub的原理及应用详解(六)

本系列文章简介&#xff1a; GitHub是一个基于Git版本控制系统的代码托管平台&#xff0c;为开发者提供了一个方便的协作和版本管理的工具。它广泛应用于软件开发项目中&#xff0c;包括但不限于代码托管、协作开发、版本控制、错误追踪、持续集成等方面。 GitHub的原理可以简单…...

基于PHP+MySQL组合开发的微信小程序分销商城源码系统 分销商城+积分商城+多商户 功能强大 带完整的安装代码包以及搭建教程

系统概述 在当今数字化商业时代&#xff0c;拥有一个强大而多功能的分销商城系统对于企业的发展至关重要。本文将重点介绍基于 PHPMySQL 组合开发的微信小程序分销商城源码系统&#xff0c;它融合了分销商城、积分商城和多商户等功能&#xff0c;不仅功能强大&#xff0c;还提…...

kafka-消费者组偏移量重置

文章目录 1、消费者组偏移量重置1.1、列出所有的消费者组1.2、查看 my_group1 组的详细信息1.3、获取 kafka-consumer-groups.sh 的帮助信息1.4、 偏移量重置1.5、再次查看 my_group1 组的详细信息 1、消费者组偏移量重置 1.1、列出所有的消费者组 [rootlocalhost ~]# kafka-…...

一书读懂Python全栈安全,剑指网络空间安全

写在前面 通过阅读《Python全栈安全/网络空间安全丛书》&#xff0c;您将能够全面而深入地理解Python全栈安全的广阔领域&#xff0c;从基础概念到高级应用无一遗漏。本书不仅详细解析了Python在网络安全、后端开发、数据分析及自动化等全栈领域的安全实践&#xff0c;还紧密贴…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...