spring源码解读-6.bean生命周期

阿里云面试:Spring 中 Bean 的生命周期是怎样的? IoC,控制反转,想必大家都知道,所谓的控制反转,就是把 new 对象的权利交给容器,所有的对象都被容器控制,这就叫所谓的控制反转。IoC 很好地体现了面向对象设计法则之一 —— 好莱坞法则:“别找我们,我们找你”,即由 IoC 容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。理解好 IoC 的关键是要明确 “谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”。谁控制谁,控制什么? 阅读详情

我们知道bean在spring中有两个大的状态。实例化,初始化;那么在bean成长过程中我们是不是可以进行干预,或者进行观察呢?自己生的孩子不可能都不管不问吧。所以在bean成长的各个环节中我们都有办法去干预,或者收到通知。spring通过暴露几个接口的方式来赋予你这个能力;

我要实例化了-> 实例化 做点啥 属性赋值 做点啥 做点啥 初始化 再做点啥

我要实例化了
实例化
我实例化好了
属性赋值
属性赋值好了
我要初始化了
初始化
我初始化好了

今天的主角
是BeanPostProcessor;作用是一个勾子,也就是一个回调函数,在bean创建的各个阶段进行回调

看下长什么样子先

public interface BeanPostProcessor {
	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

在bean初始化 前后会调用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization

该接口执行逻辑在doCreateBean中调用的initializeBean里面;绝大部分的BeanPostProcessor都是在这里执行调用的。也有特殊。先看大部分的:
路标: applyBeanPostProcessorsBeforeInitialization,和applyBeanPostProcessorsAfterInitialization就是在执行初始化方法invokeInitMethods之前和之后调用
BeanPostProcessor用的;

	protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareMethods(beanName, bean);
					return null;
				}
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}

		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

特殊情况是InstantiationAwareBeanPostProcessor; 是postProcessor的一个子类
比postProcessor多了三个接口

接口作用
postProcessBeforeInitialization初始化前
postProcessAfterInitializationpost初始化后调用
ProcessBeforeInstantiation实例化之前调用
postProcessAfterInstantiation实例化之后调用
postProcessPropertyValues属性赋值后回调

初始化前后上面看过了。下面看另外三个。

1.实例化前
源码位置在:createBean->resolveBeforeInstantiation
**路标:applyBeanPostProcessorsBeforeInstantiation **
注意:这里如果用户自己实例化bean并且返回了。那么后面由spring创建bean的逻辑就会不执行。直接执行applyBeanPostProcessorsAfterInitialization逻辑,也就是直接执行初始化成功回调。另外的实例化后和属性赋值后逻辑都不会执行了。为什么呢?你喵的都自己创建对象了,那么属性赋值肯定是你自己搞定了。也就是说实例化和属性赋值都是你自己弄得,那生命周期你自己都知道了自己加逻辑就是了。就没必要再绕一圈让spring通知你了。就像是你自己干了一件事,然后还让别人告诉你你干了啥?你干了啥你自己心里没数吗?

	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

2:实例化后
实例化之后逻辑:postProcessAfterInstantiation
位置在populateBean中InstantiationAwareBeanPostProcessor注意这里调用该接口如果返回false则会中断属性赋值继续往下执行

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
		PropertyValues pvs = mbd.getPropertyValues();

		if (bw == null) {
			if (!pvs.isEmpty()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		boolean continueWithPropertyPopulation = true;

		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
						continueWithPropertyPopulation = false;
						break;
					}
				}
			}
		}

		if (!continueWithPropertyPopulation) {
			return;
		}

		if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
				mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

			// Add property values based on autowire by name if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}

			// Add property values based on autowire by type if applicable.
			if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}

			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

		if (hasInstAwareBpps || needsDepCheck) {
			PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			if (hasInstAwareBpps) {
				for (BeanPostProcessor bp : getBeanPostProcessors()) {
					if (bp instanceof InstantiationAwareBeanPostProcessor) {
						InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
						pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvs == null) {
							return;
						}
					}
				}
			}
			if (needsDepCheck) {
				checkDependencies(beanName, mbd, filteredPds, pvs);
			}
		}

		applyPropertyValues(beanName, mbd, bw, pvs);
	}
Spring 的并发问题 - 有状态 Bean 和无状态 Bean 当多个线程同时访问有状态Bean时,可能会引发并发问题,因为每个线程可能会访问和修改相同的状态数据,导致数据不一致或竞态条件。通过将有状态Bean的方法标记为事务,可以在方法执行期间启用数据库事务,从而避免数据并发访问的问题。在Spring框架中,通过合理地设计Bean的作用域(Scope)和避免在有状态Bean中保存状态信息,可以有效地处理并发问题。通过选择适当的作用域,可以在一定程度上控制有状态Bean的生命周期和访问范围,减少并发问题的影响。尽量设计有状态Bean,使其尽可能避免共享状态数据。 阅读详情

相关推荐

1.2 Bean 的一生:从 BeanDefinition 到销毁,Spring 做了 15 件事

本文深入解析Spring Bean生命周期的15个关键阶段,从BeanDefinition注册到销毁过程。详细阐述了实例化前回调、属性注入、Aware接口回调、初始化前后处理(包括@PostConstruct、InitializingBean、init-method的执行顺序)等核心环节,特别分析了解决循环依赖的三级缓存机制和AOP代理生成时机。通过逐行源码分析(v6.2.0)揭示Spring IoC容器如何管理Bean的完整生命周期,帮助开发者深入理解Spring框架的设计原理。

小林夕程的博客 212

Spring 有状态bean 无状态bean

https://blog.csdn.net/anyoneking/article/details/5182164 在Spring的Bean配置中,存在这样两种情况:   [xhtml] view plain copy &lt;bean id="testManager" class="com.sw.TestManagerImpl" scope="singleton" /&gt;      ...

伏虎游侠的博客 1万+

【G4基础08】GPS-2-Macro Commands宏命令

GPS-2

adelall的博客 3738

有状态会话bean和无状态会话bean

Spring单例bean 线程安全

dabaicai0402的博客 1919

树莓派与无人机协同实战:基于OpenCV的地标识别优化策略

本文深入探讨了基于树莓派与无人机的协同系统,重点分享了利用OpenCV优化地标识别以实现精准降落的实战策略。内容涵盖从应对复杂光照的图像预处理、鲁棒的轮廓几何过滤,到通过ROS进行稳定通信,以及实现分层控制与状态机设计,旨在提升系统在真实环境中的可靠性与性能。

y2z3a4b5c的博客 1086

Linux显卡管理避坑指南:为什么Xorg总是占用你的NVIDIA GPU?

本文深入解析了在Linux系统上,尤其是双显卡笔记本中,Xorg显示服务器进程占用NVIDIA GPU的根本原因。文章从Xorg的驱动加载机制和NVIDIA驱动的独占性入手,详细对比了禁用配置文件、手动配置xorg.conf、使用官方PRIME方案以及切换到Wayland等主流解决方案的优缺点与适用场景,旨在帮助用户有效释放GPU资源,确保深度学习、游戏等计算任务能独占显卡性能。

xgboost6farmer的博客 268

Spring的Bean生命周期有哪些阶段?

Spring的Bean生命周期分为四个阶段:实例化、属性赋值、初始化和销毁。destroy()在整个生命周期中,多个增强接口贯穿了这四个阶段,例如接口可以用于对Bean进行后置处理,接口可以用于处理注解等。这些增强接口为开发者提供了更灵活和强大的功能。

luoluoal的博客 1049

OpenHarmony-AI调研

基于OpenHarmony-5.0.0版本以及laval社区等网络资料调研当前OH上的AI发展情况。

qqq1112345的博客 1369

Spring的scope属性_002

  摘自《Spring 解密》 scope用来声明IOC容器中的对象应该处的限定场景或者说该对象的存活空间,即在IOC容器在对象进入相应的scope之前,生成并装配这些对象,在该对象不再处于这些scope的限定之后,容器通常会销毁这些对象。打个比方吧!我们都是处在社会(容器)中,如果把中学教师作为一个类定义,那么当容器初始化这些类之后,中学教师只能局限在中学这个场景中,中学,就可以看...

SpringJava的博客 301

金蝶云星空应用开发初级考试题目汇总

摘要:本文为金蝶云星空应用开发初级考试题目汇总

2401_86113757的博客 3799

扫地机器人设计与实现——基于嵌入式系统的智能家居解决方案

本文介绍了基于嵌入式技术的扫地机器人设计与实现。通过利用STM32单片机、传感器、驱动系统等硬件组件,并结合路径规划与控制算法、远程控制等软件技术,设计出了一款具有智能避障、路径规划、自动充电等功能的扫地机器人。系统的开发不仅提高了清洁效率,也为进一步研究和优化扫地机器人提供了实践基础。

2201_76125393的博客 1639

Spring Bean 全方位指南:从作用域、生命周期到自动配置详解

SpringBean 那些事

2401_83595513的博客 1799

SQL注入详解

SQL注入(SQL Injection)是一种常见的Web安全漏洞,主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行。 从而导致数据库受损(被脱库、被删除、甚至整个服务器权限陷)。 即:注入产生的原因是后台服务器接收相关参数未经过滤直接带入数据库查询...

渗透之路,攻防之间皆学问 26万+

Spring干货---IOC

spring ioc介绍,只讲干货,不说废话

zhzhxian的博客 421

《AgentScope-Java 深入浅出教程》第3章 消息系统(Message)

在 AgentScope 中,消息(Msg)是最核心的数据结构。│ 消息的作用 ││ ││ │ 用户输入 │ ────────────┐ ││ ▼ ││ │智能体通信│ ◄────► │ 消息对象 │ ◄────► │ LLM API │ ││ ▲ ││ │ ││ │ 历史存储 │ ────────────┘ ││ │用户输入:封装用户的问题和指令智能体输出:封装智能体的回复和工具调用智能体通信:在多智能体系统中传递信息LLM API 交互:转换为 LLM 可理解的格式历史存储。

步子哥的博客 228

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

一文读懂 Spring Bean 的生命周期

欢迎大家关注我的微信公众号【老周聊架构】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。 一、前言 今天我们来说一说 Spring Bean 的生命周期,小伙伴们应该在面试中经常遇到,这是正常现象。因为 Spring Bean 的生命周期是除了 IoC、AOP 几个核心概念之外最重要概念,大家务必拿下。可 Spring 源代码又比较复杂,跟着跟着就不知道跟到哪里去了,不太好拿下呀。这倒是真的,而且网上一上来就各种贴流程源码,对初学者来说是真的一脸懵逼,就像字.

riemann_的博客 12万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

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

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

Code豪客 2039

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Spring原理—Bean的生命周期

首先来介绍一下循环依赖问题,假设对象A的属性是对象B,对象B的属性是对象A,那么在实例化A和B时,首先实例化A,发现属性对象B未实例化,此时实例化B又发现属性对象A不存在(A实例化了但是属性为注入,因此A不是一个完整的对象,不能直接使用),此时又触发实例化A,反复循环,直到内存溢出。在循环依赖中的核心问题在于属性注入期间,由于加载了一半的对象无法直接使用,导致无法进行属性注入,也就导致对象的初始化一直不会完成,抛出BeanCurrentlyInCreationException的异常。

sniper_fandc的博客 1450

Spring bean生命周期的源码分析(超级详细)

文章目录一. 问题背景二. 储备知识三. 问题引入3.1 循环依赖3.2 对循环依赖的分析3.3 两个小结论3.4 验证两个小结论 一. 问题背景 遇到面试题“Spring Bean的生命周期是怎么样?”,很多网上的博客博文都有总结性的阐述,但是笔者想知道是从哪里开始切入到Spring Bean的生命周期,从什么时候开始,从哪句代码开始研究。因此今天研究一下Spring源码分析Spring Bean的生命周期。 此笔记仅供自己参考,如有错误请指正 参考自: 请别再问Spring Bean的生命周期了! 【

Android_la的博客 3684

Spring5源码 - 06 Spring Bean 生命周期流程 概述 01

文章目录Bean生命周期概述Demo Bean生命周期概述 说到Spring Bean的生命周期,其实就是探究Spring Bean实例化经历哪些步骤了 本篇博文先给个整体的解读,下文将从源码上来探究Spring Bean的生命周期过程。 Demo 先跑通一个小demo ...

小工匠 2万+

Spring的Bean生命周期源码解读

spring源码解析

qq_45887180的博客 495

Spring5源码 - 07 Spring Bean 生命周期流程 源码解读02

文章目录PrefinishBeanFactoryInitialization Pre Spring5源码 - 06 Spring Bean 生命周期流程 概述 01 接上文 finishBeanFactoryInitialization /** * Finish the initialization of this context's bean factory, * initializing all remaining singleton beans. */ protected void

小工匠 2万+

Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程

从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释

种一棵树最好的时间是十年前,其次是现在 3975

深度解析 Spring 源码:揭秘 AbstractAutowireCapableBeanFactory 的 Bean 生命周期处理

本文深入解析了 Spring 框架中的核心组件之一AbstractAutowireCapableBeanFactory,重点揭秘了其在 Bean 生命周期处理中的关键作用。首先,我们探讨了 Spring IoC(控制反转)和 DI(依赖注入)的基本原理,以及 AbstractAutowireCapableBeanFactory 在其中的地位和作用。通过本文的阐述,读者将深入了解 Spring 框架中 Bean 的生命周期处理机制,为进一步理解和应用 Spring 框架提供了重要参考。

忆~遂愿的博客 2800

Spring bean的生命周期,对比源码详解

为了更加熟悉spring的总体流程,看了spring的源码。 看了很多网上的资料写的spring的bean的生命周期,但是感觉和看到的源码有部分出入,这里再总结下。 正文: spring获取bean的时候有两种方式: BeanFactory bf = new XmlBeanFactory(new ClassPathResource("appli...

Jeff的专栏 5505

Bean 生命周期详解

IoC,控制反转,想必大家都知道,所谓的控制反转,就是把 new 对象的权利交给容器,所有的对象都被容器控制,这就叫所谓的控制反转。IoC 很好地体现了面向对象设计法则之一 —— 好莱坞法则:“别找我们,我们找你”,即由 IoC 容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。理解好 IoC 的关键是要明确 “谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”。谁控制谁,控制什么?

weixin_45985053的博客 4603
上一篇: spring源码解读-5.容器生命周期之修改图纸
下一篇: Spring源码解读-第一部分核心部分
掀衣怒码
博客等级 码龄6年 6粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值