Spring中Bean生命周期及循环依赖

news2024/11/15 15:31:13

spring中所说的bean对象我们自己new的对象(原始对象)是不同的;

bean对象是指spring框架创建管理的我们的对象

生命周期即:何时生,何时死

1.实例化 Instantiation:

spring通过反射机制以及工厂创建出来的原始对象;

2.属性赋值 Populate:

对对象中属性进行赋值操作

3.初始化 Ininitialization:

在这个阶段完成对原始对象的各种功能增强,如AOP生成代理对象、实现下面的接口方法等:

这些是初始化阶段可以实现的接口,以及接口中的方法:
3.1 如果 Bean 实现 BeanNameAware 执行 setBeanName
3.2 如果 Bean 实现 BeanFactoryAware 或者ApplicationContextAware 设 置工厂 setBeanFactory 或者上下文对象 setApplicationContext 对象.
3.3 如果存在类实现 BeanPostProcessor(AOP),执行postProcessBeforeInitialization
3.4 如果 Bean 实现 InitializingBean 执行 afterPropertiesSet如果配置了自己的初始化方法<bean init-method="init">
3.5 如果存在类实现 BeanPostProcessor(AOP) ,执行postProcessAfterInitialization

如下@transactional标签实现事务管理,同时这个类也实现了两个接口,实现了接口的方法:

这些都是在初始化阶段需要完成的;等这些都完成后,bean对象就算是真正意义上的创建完成了

完成后就把bean对象放入到容器中使用

4.销毁

如果 Bean 实现 DisposableBean 执行 destroy 如果配置了自己的销毁方法<bean destroy-method="customerDestroy">

指定销毁方法 customerDestroy

bean生命周期具体流程图:

Spring中的bean是线程安全的吗?

servlet是线程安全的吗?不是,因为servlet对象只创建了一个,所以属性值也就只有一个,当有多个请求(线程)访问同一个值时,就会出现线程安全问题、共享问题;

spring中的bean是否是线程安全的,要看它的作用域,即scope

若是Singleton,即单例,那就是线程不安全,所有线程都共享一个单例实例Bean,可以使用ThreadLocal解决,为每一个线程创建一个变量副本;

若是prototype,即原型的 多例 是线程安全的,一个请求到来,创建一个对象,bean之间不存在Bean共享,自然不会出现线程安全问题。

bean又分为 有状态bean无状态bean

1.有状态:可以用来存储数据

2.无状态:不会存储数据,如Service层,Dao层只是方法调用

如果单例 Bean,是一个无状态 Bean,也就是线程中的操作不会对 Bean 的成员执行查询以外的操作,那么这个单例 Bean 是线程安全的。比如 Spring mvc 的 Controller、Service、Dao 等,这些 Bean 大多是无状态的,只关注于方法本身。

但是如果单例Bean 是有状态的,那就不能保证线程安全, 那就需要开发人员自己来进行线程安全的保证,最简单的办法1.就是改变 bean 的作用域把 "singleton"改为’‘protopyte’‘, 这样每次请求 Bean 就相当于是 new Bean() 这样就可以保证线程的安全了。 2.就是使用Threadlocal线程池存储变量,为每个线程创建一个变量副本

controller、service 和 dao 层本身并不是线程安全的,只是如果只是调用里面的方法,而且多线程调用一个实例的方法,会在内存中复制变量,这是自己的线程的工作内存,是安全的。

Bean循环依赖


java中循环依赖场景:

很简单,A类关联了B类,B类同时也关联了A类;

如果是纯粹的java语言,即不考虑spring,自己new对象时,是没有任何问题的,因为对象之间相互关联是很常见的事,我们直接将关联在内的对象初始化赋值为null,然后相互赋值即可,如下。

Spring产生循环依赖问题

但是在spring管理bean时,在自动注入时,如果两个类相互之间关联,那么会出现注入一个对象时,另一个对象还没有初始化完成(bean对象需要经历初始化过程)。总之一个对象并不会简单new出来,而是会经过一系列的Bean的声明周期,就是因为Bean的生命周期所以才会出现循环依赖问题。

如何产生循环依赖问题:主要是:A创建时→需要B----B去创建→又需要A

Spring解决循环依赖

spring提供了 三级缓存机制来解决这个问题:

在 DefaultSingletonBeanRegistry 类中定义了 3 个 Map 对象充当缓存;

singletonObjects: 一级缓存,用于保存实例化、注入、初始化完成的 bean实例,即已经完全初始化的bean对象;

earlySingletonObjects:二级缓存,用于保存实例化完成的 半成品bean 实例,即就是刚创建出的半成品对象,未经初始化,提前曝露对象给需要的地方。

singletonFactories: 三级缓存,用于保存创建 bean 对象的工厂

具体过程:

当A中需要B时,那么先从一级缓存中找B,没有,然后到二级缓存中找B,若也没有,则去三级缓存中,找到B对应的工厂,创建出B对象(原始对象,半成品),把B对象存入二级缓存中,如下:

主要通过三级缓存解决Bean循环依赖问题:

出现问题的根本原因是实例化和初始化是分开处理的。

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

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

相关文章

【Spring】八种常见Bean加载方式

&#x1f6a9;本文已收录至专栏&#xff1a;Spring家族学习 一.引入 (1) 概述 ​ 关于bean的加载方式&#xff0c;spring提供了各种各样的形式。因为spring管理bean整体上来说就是由spring维护对象的生命周期&#xff0c;所以bean的加载可以从大的方面划分成2种形式&#xff…

2023年融资融券研究报告

第一章 行业概况 融资融券是证券交易市场上的两种金融衍生品交易方式&#xff0c;主要用于股票、债券等证券的融资和投资。 融资是指投资者向证券公司借入资金购买证券&#xff0c;以期望股票价格上涨后卖出获得利润。融资需支付一定的利息和费用&#xff0c;利息根据借入的资…

CSS实现checkbox选中动画

前言 &#x1f44f;CSS实现checkbox选中动画&#xff0c;速速来Get吧~ &#x1f947;文末分享源代码。记得点赞关注收藏&#xff01; 1.实现效果 2.实现步骤 定义css变量&#xff0c;–checked&#xff0c;表示激活选中色值 :root {--checked: orange; }创建父容器&#xf…

python+pytest接口自动化(6)-请求参数格式的确定

我们在做接口测试之前&#xff0c;先需要根据接口文档或抓包接口数据&#xff0c;搞清楚被测接口的详细内容&#xff0c;其中就包含请求参数的编码格式&#xff0c;从而使用对应的参数格式发送请求。例如某个接口规定的请求主体的编码方式为 application/json&#xff0c;那么在…

Go 实现 AOI 区域视野管理

在游戏中,场景里存在大量的物体.如果我们把所有物体的变化都广播给玩家.那客户端很难承受这么大的压力.因此我们肯定会做优化.把不必要的信息过滤掉.如只关心玩家视野所看到的.减轻客户端的压力,给玩家更流畅的体验. 优化的思路一般是: 第一个是尽量降低向客户端同步对象的数量…

【Java】P1 基础知识与碎碎念

Java 基础知识 碎碎念安装 Intellij IDEAJDK 与 JREJava 运行过程Java 系统配置Java 运行过程Java的三大分类前言 本节内容主要围绕Java基础内容&#xff0c;从Java的安装到helloworld&#xff0c;什么是JDK与什么是JRE&#xff0c;系统环境配置&#xff0c;不深入Java代码知识…

传导EMI抑制-Π型滤波器设计

1 传导电磁干扰简介 在开关电源中&#xff0c;开关管周期性的通断会产生周期性的电流突变&#xff08;di/dt&#xff09;和电压突变(dv/dt)&#xff0c;周期性的电流变化和电压变化则会导致电磁干扰的产生。 图1所示为Buck电路的电流变化&#xff0c;在Buck电路中上管电流和下…

ubuntu 22.04 mangodb

文章写在2023年3月1日 目前最新的mangodb稳定版本是6.04 1.安装server server安装包为mangodb的程序主体。 服务器deb安装包下载地址 https://www.mongodb.com/try/download/community ubuntu22.04的server deb 文件url https://repo.mongodb.org/apt/ubuntu/dists/jammy/mo…

计算机组成原理 浮点数运算清晰明了

注释&#xff1a;阶码和尾数都需要符号位区分正负 例题1&#xff1a;x 2^-11*0.100101&#xff0c; y 2^-10*(-0.011110)&#xff0c;求xy 第零步 补码表示 对于x来说-11 补码表示为 11011&#xff1b; 0.100101补码表示为00.100101对于y来说-10补码表示为 10110&#xff…

【el】表单

elementUI中的表单相关问题一、用法1、动态表单调用接口返回表单&#xff0c;后端的接口返回值如下&#xff1a;这些是渲染后的效果页面使用&#xff08;父组件&#xff09;<el-button size"small" class"Cancelbtn" click"sub(true)">发起…

python程序员狂飙上头——京海市大嫂单推人做个日历不过分吧?

嗨害大家好鸭&#xff01;我是小熊猫~ 这个反黑剧其实火了很久了&#xff0c; 但是我现在才有空开始看 该说不说&#xff0c;真的很上头&#xff01;&#xff01;&#xff01; 大嫂简直就像是干枯沙漠里的玫瑰 让人眼前一亮哇~~ 我小熊猫此时此刻就成为大嫂的单推人&…

Auto-encoder 系列

Auto-Encoder (AE)Auto-encoder概念自编码器要做的事&#xff1a;将高维的信息通过encoder压缩到一个低维的code内&#xff0c;然后再使用decoder对其进行重建。“自”不是自动&#xff0c;而是自己训练[1]。PCA要做的事其实与AE一样&#xff0c;只是没有神经网络。对于一个输入…

Django学习——基础篇(上)

一、Django的安装 pip install djangopython目录下出现两个文件 djando-admin.exe django django-admin.exe django 二、创建项目 1.命令行&#xff08;终端&#xff09; 1.打开终端 winR 输入cmd 2.进入项目目录 3.执行命令创建项目 2.Pycharm 两种方法对比 1.命令行创…

FL Studio21中文版本下载更新内容详细介绍

FL Studio推出全新21版&#xff0c;为原创音乐人提供更好用的DAW&#xff08;数字音乐工作站&#xff09;工具。FL Studio国人也叫它水果编曲软件&#xff0c;是一款有着22多年历史的经典音乐创作软件。已有上千万的用户每天在使用水果编曲创作自己的音乐。它被公认为最适合新手…

Stochastic Approximation 随机近似方法的详解之(一)

随机近似的定义&#xff1a;它指的是一大类随机迭代算法&#xff0c;用于求根或者优化问题。 Stochastic approximation refers to a broad class of stochastic iterative algorithms solving root finding or optimization problems. temporal-difference algorithms是随机近…

原子级操作快速自制modbus协议

原子级操作手把手搞懂modbus协议文章目录[toc]1 modbus协议基础概念1.1 使用场所1.2 主从协议站1.3 modbus帧描述1.4 数据模式1.5 modbus状态机2 modbus协议2.1 功能码2.2 公共功能码2.3 数据域格式3 modbus从站程序设计3.1 接口初始化3.2 数据处理部分查表法设置超时时间3.2 主…

堆的概念结构及实现

文章目录1.堆的概念及结构2.堆的实现2.1父子节点之间的关系2.2堆的向上排序算法2.3 堆的删除2.4堆的向下排序算法2.5入堆2.6堆的创建2.6.1通过入堆实现&#xff08;通过向上堆排序&#xff09;2.6.2通过向下排序实现2.6.3两种方法比较2.7代码实现2.7.1函数声明2.7.2函数实现2.7…

前端开发与vscode开发工具介绍

文章目录1、前端开发2、vscode安装和使用2.1、下载地址2.2、插件安装2.3、设置字体大小2.4、开启完整的Emmet语法支持2.5、创建项目2.6、保存工作区2.7、新建文件夹和网页1、前端开发 前端工程师“Front-End-Developer”源自于美国。大约从2005年开始正式的前端工程师角色被行…

【Python入门第二十一天】Python 数组

请注意&#xff0c;Python 没有内置对数组的支持&#xff0c;但可以使用 Python 列表代替。 数组 数组用于在单个变量中存储多个值&#xff1a; 实例 创建一个包含汽车品牌的数组&#xff1a; cars ["Porsche", "Volvo", "BMW"]运行实例 …

【我的车载技术】 Android AutoMotive 之 init与zygote内核原理

init概述 init是一个进程&#xff0c;确切地说&#xff0c;它是Linux系统中用户空间的第一个进程。由于Android是基于Linux内核的&#xff0c;所以init也是Android系统中用户空间的第一个进程&#xff0c;它的进程号是1。作为天字第一号的进程&#xff0c;init被赋予了很多极其…