面试题:Spring Bean的生命周期

article/2025/8/24 3:25:05

最近在复习Spring的面试题,关于Spring Bean的生命周期一直没有很深入的理解,自己结合源码参考了网上的几篇文章,写了一点东西,方便理解。
请添加图片描述

  1. Spring 启动,查找并加载需要被 Spring 管理的 Bean,进行 Bean 的实例化;
  2. Bean 实例化后,对 Bean 的引入和值注入到 Bean 的属性中;
  3. 如果 Bean 实现了 BeanNameAware 接口的话,Spring 将 Bean 的 Id 传递给 setBeanName() 方法;
  4. 如果 Bean 实现了 BeanFactoryAware 接口的话,Spring 将调用 setBeanFactory() 方法,将 BeanFactory 容器实例传入;
  5. 如果 Bean 实现了 ApplicationContextAware 接口的话,Spring 将调用 Bean 的 setApplicationContext() 方法,将 Bean 所在应用上下文引用传入进来;
  6. 如果 Bean 实现了 BeanPostProcessor 接口,Spring 就将调用它们的postProcessBeforeInitialization() 方法;
  7. 如果 Bean 实现了 InitializingBean 接口,Spring 将调用它们的 afterPropertiesSet() 方法。类似地,如果 Bean 使用 init-method 声明了初始化方法,该方法也会被调用;
  8. 如果 Bean 实现了 BeanPostProcessor 接口,Spring 就将调用它们的 postProcessAfterInitialization() 方法;
  9. 此时,Bean 已经准备就绪,可以被应用程序使用了。它们将一直驻留在应用上下文中,直到应用上下文被销毁;
  10. 如果 Bean 实现了 DisposableBean 接口,Spring 将调用它的 destory() 接口方法,同样,如果 Bean 使用了 destory-method 声明销毁方法,该方法也会被调用。

让我们结合源码捋一遍这个过程,主要的过程在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.java这个类中

AbstractAutowireCapableBeanFactory.java    initializeBean()方法protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {/*** 调用Bean实现的Aware接口的方法,主要包括下面三个接口* BeanNameAware ----> setBeanName()* BeanClassLoaderAware ----> setBeanClassLoader()* BeanFactoryAware  ----> setBeanFactory()*/invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {/** 调用Bean对象的postProcessBeforeInitialization方法,此处会执行标注@PostConstruct注解的方法 */// 此处会调用ApplicationContextAwareProcessor执行其他的aware方法.wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {/*** 执行Bean的初始化方法:** 1.先判断Bean是否实现了InitializingBean接口,如果实现了InitializingBean接口,则调用Bean对象的afterPropertiesSet方法;* 2.然后判断Bean是否有指定init-method方法,如果指定了init-method方法,则调用bean对象的init-method指定的方法.*/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()) {/*** 调用Bean对象的postProcessAfterInitialization方法** 如果需要创建代理,在该步骤中执行postProcessAfterInitialization方法的时候会去创建代理* 调用AbstractAutoProxyCreator类的postProcessAfterInitialization方法,然后调用wrapIfNecessary方法去创建代理.*** 另外还有一些Aware接口,也会在该步骤中执行,例如:ApplicationContextAwareProcessor后置处理器,对应的setApplicationContext方法会被执行.*/wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}
  1. 如果 Bean 实现了 BeanNameAware 接口的话,Spring 将 Bean 的 Id 传递给 setBeanName() 方法;
  2. 如果 Bean 实现了 BeanFactoryAware 接口的话,Spring 将调用 setBeanFactory() 方法,将 BeanFactory 容器实例传入;
  3. 如果 Bean 实现了 ApplicationContextAware 接口的话,Spring 将调用 Bean 的 setApplicationContext() 方法,将 Bean 所在应用上下文引用传入进来;
AbstractAutowireCapableBeanFactory.java/*** 执行所有的Aware接口中的方法* @param beanName bean的名称* @param bean bean对象*/private void invokeAwareMethods(final String beanName, final Object bean) {// 如果Bean实现了Aware接口if (bean instanceof Aware) {// 如果实现了BeanNameAware接口,则调用Bean的setBeanName方法if (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}// 如果实现了BeanClassLoaderAware接口,则调用Bean的setBeanClassLoader方法if (bean instanceof BeanClassLoaderAware) {ClassLoader bcl = getBeanClassLoader();if (bcl != null) {((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}// 如果实现了BeanFactoryAware接口,则调用Bean的setBeanFactory方法if (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}}ApplicationContextAwareProcessor.javaprivate void invokeAwareInterfaces(Object bean) {if (bean instanceof Aware) {//....////如果 Bean 实现了 ApplicationContextAware 接口的话,Spring 将调用 Bean 的 setApplicationContext() 方法,//将 Bean 所在应用上下文引用传入进来;if (bean instanceof ApplicationContextAware) {((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);}}}
  1. 如果 Bean 实现了 BeanPostProcessor 接口,Spring 就将调用它们的postProcessBeforeInitialization() 方法;
public interface BeanPostProcessor {// 该方法是Spring后置处理器中的方法// 该方法是在Bean实例化(new)之后,初始化(设置各种属性)之前会被调用// 在调用afterPropertiesSet方法之前会被调用@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}// 在bean初始化之后会被调用// 在调用InitializingBean的afterPropertiesSet方法或者init-method指定的方法执行之后调用.@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}}
AbstractAutowireCapableBeanFactory.java@Overridepublic Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {/** 调用InitDestroyAnnotationBeanPostProcessor来处理标注有@PostConstruct注解的方法. *//** 执行ApplicationContextAwareProcessor的postProcessBeforeInitialization*/Object current = processor.postProcessBeforeInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
  1. 如果 Bean 实现了 InitializingBean 接口,Spring 将调用它们的 afterPropertiesSet() 方法。类似地,如果 Bean 使用 init-method 声明了初始化方法,该方法也会被调用;
AbstractAutowireCapableBeanFactory.javaprotected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)throws Throwable {// 判断bean对象是否为InitializingBean的实例// 如果实现了InitializingBean接口,则只掉调用bean的afterPropertiesSet方法boolean isInitializingBean = (bean instanceof InitializingBean);if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {if (logger.isTraceEnabled()) {logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");}if (System.getSecurityManager() != null) {try {AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((InitializingBean) bean).afterPropertiesSet();return null;}, getAccessControlContext());}catch (PrivilegedActionException pae) {throw pae.getException();}}else {((InitializingBean) bean).afterPropertiesSet();}}// 判断是否指定了init-method方法,如果指定了init-method方法,而且初始化方法不是afterPropertiesSet//  则通过反射执行指定的初始化方法if (mbd != null && bean.getClass() != NullBean.class) {// 获取初始化方法的名称String initMethodName = mbd.getInitMethodName();if (StringUtils.hasLength(initMethodName) &&!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&!mbd.isExternallyManagedInitMethod(initMethodName)) {// 调用init-method方法时也是通过反射实现invokeCustomInitMethod(beanName, bean, mbd);}}}
  1. 如果 Bean 实现了 BeanPostProcessor 接口,Spring 就将调用它们的 postProcessAfterInitialization() 方法;
AbstractAutowireCapableBeanFactory.java 
调用Bean对象的postProcessAfterInitialization方法@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {// 该步骤中会创建代理类.// 在bean初始化之后会被调用// 在调用InitializingBean的afterPropertiesSet方法或者init-method指定的方法执行之后调用.Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}
  1. 此时,Bean 已经准备就绪,可以被应用程序使用了。它们将一直驻留在应用上下文中,直到应用上下文被销毁;
  2. 如果 Bean 实现了 DisposableBean 接口,Spring 将调用它的 destory() 接口方法,同样,如果 Bean 使用了 destory-method 声明销毁方法,该方法也会被调用。
DisposableBeanAdapter.java@Overridepublic void destroy() {//...//if (this.invokeDisposableBean) {if (logger.isDebugEnabled()) {logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");}try {// 9. 若实现 DisposableBean 接口,则执行 destory()方法if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((DisposableBean) bean).destroy();return null;}, acc);}else {((DisposableBean) bean).destroy();}}catch (Throwable ex) {//...//}}// 10. 若配置自定义的 detory-method 方法,则执行if (this.destroyMethod != null) {invokeCustomDestroyMethod(this.destroyMethod);}else if (this.destroyMethodName != null) {Method methodToCall = determineDestroyMethod(this.destroyMethodName);if (methodToCall != null) {invokeCustomDestroyMethod(methodToCall);}}}

总结:

  • 首先是实例化、属性赋值、初始化、销毁这 4 个大阶段;
  • 再是初始化的具体操作,有 Aware 接口的依赖注入、BeanPostProcessor 在初始化前后的处理以及 InitializingBean 和 init-method 的初始化操作;
  • 销毁的具体操作,有注册相关销毁回调接口,最后通过DisposableBean 和 destory-method 进行销毁。

http://chatgpt.dhexx.cn/article/1Q6d7m1i.shtml

相关文章

Bean的生命周期和作用域

Bean的生命周期 Bean的执行流程&#xff1a; Bean 执行流程&#xff1a;启动Spring 容器 -> 实例化 Bean&#xff08;分配内存空间&#xff0c;从无到有&#xff09;-> Bean 注册到 Spring 中&#xff08;存操作&#xff09; -> 将 Bean 装配到需要的类中&#xff08;…

关于Spring Bean的生命周期

一、简介 Spring Bean 的生命周期在整个 Spring 中占有很重要的位置&#xff0c;从BeanFactory或ApplicationContext取得的实例为Singleton&#xff0c;也就是预设为每一个Bean的别名只能维持一个实例&#xff0c;而不是每次都产生一个新的对象使用Singleton模式产生单一实…

7、Bean的生命周期

Spring其实就是一个管理Bean对象的工厂。它负责对象的创建&#xff0c;对象的销毁等。 所谓的生命周期就是&#xff1a;对象从创建开始到最终销毁的整个过程。 什么时候创建Bean对象&#xff1f; 创建Bean对象的前后会调用什么方法&#xff1f; Bean对象什么时候销毁&#…

【一篇搞懂】 bean的生命周期详解

概述 Spring中的一个Bean从生到灭要经历很多过程,总体分为Bean定义、实例化、属性赋值(依赖注入)、初始化、生存期、销毁几个阶段: ​​​​​​​​ 下面是一个细化的Bean生命周期图: 过程比较复杂,重点关注Bean的定义、初始化、销毁过程,可以抓住重点: BeanPostPro…

Bean 生命周期详解

Spring Bean 的生命周期&#xff0c;面试时非常容易问&#xff0c;这不&#xff0c;前段时间就有个粉丝去字节面试&#xff0c;因为不会回答这个问题&#xff0c;一面都没有过。 如果只讲基础知识&#xff0c;感觉和网上大多数文章没有区别&#xff0c;但是我又想写得稍微深入…

【Spring】Spring的Bean的生命周期

作者简介&#xff1a;大家好&#xff0c;我是五度鱼&#xff0c;一个普通的Java领域博主&#xff0c;不停输出Java技术博客和干货。座右铭&#xff1a;锲而不舍&#xff0c;金石可镂。个人主页&#xff1a;五度鱼学Java的主页 文章目录 前言1. 什么是Bean的生命周期&#xff1f…

Spring中bean的生命周期(最详细)

Spring Bean的生命周期是Spring面试热点问题。Spring Bean的生命周期指的是从一个普通的Java类变成Bean的过程&#xff0c;深知Spring源码的人都知道这个给面试官讲的话大可讲30分钟以上&#xff0c;如果你不没有学习过Spring的源码&#xff0c;可能就知道Aware接口和调用init方…

Bean的生命周期

目录 一&#xff0c;bean的初始化 &#xff08;1&#xff09;Spring的IOC和AOP&#xff1a; &#xff08;2&#xff09;Spring Bean的生命周期&#xff1a; 二&#xff0c;单例模式与多例模式的区别 区别 《代码演示》 前言 回顾&#xff1a;Servlet的生命 初始化&#x…

bean的生命周期(最全最细讲解)

一、bean生命周期&#xff1a; 其定义为&#xff1a;从对象的创建到销毁的过程。而Spring中的一个Bean从开始到结束经历很多过程&#xff0c;但总体可以分为六个阶段Bean定义、实例化、属性赋值、初始化、生存期、销毁。 二、案例代码演示 1.首先我们来创建一个包&#xff0…

去字节面试,直接让人出门左拐:Bean 生命周期都不知道!

Spring Bean 的生命周期&#xff0c;面试时非常容易问&#xff0c;这不&#xff0c;前段时间就有个粉丝去字节面试&#xff0c;因为不会回答这个问题&#xff0c;一面都没有过。 如果只讲基础知识&#xff0c;感觉和网上大多数文章没有区别&#xff0c;但是我又想写得稍微深入…

Spring Bean生命周期,好像人的一生。。

大家好&#xff0c;我是老三&#xff0c;上节我们手撸了一个简单的IOC容器五分钟&#xff0c;手撸一个Spring容器&#xff01;&#xff0c;这节我们来看一看Spring中Bean的生命周期&#xff0c;我发现&#xff0c;和人的一生真的很像。 简单说说IoC和Bean IoC&#xff0c;控制…

Spring中bean的生命周期

Spring中的bean的生命周期主要包含四个阶段&#xff1a;实例化Bean --&#xff1e; Bean属性填充 --&#xff1e; 初始化Bean --&#xff1e;销毁Bean 首先是实例化Bean&#xff0c;当客户向容器请求一个尚未初始化的bean时&#xff0c;或初始化bean的时候需要注入另一个尚末初…

一文读懂 Spring Bean 的生命周期

欢迎大家关注我的微信公众号【老周聊架构】&#xff0c;Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。 一、前言 今天我们来说一说 Spring Bean 的生命周期&#xff0c;小伙伴们应该在面试中经常遇到&#xff0c;这是正常现象。…

ubuntu 换源深层次解析

换源也是一个容易出错的问题&#xff0c;本文以树莓派为例展开&#xff0c;x86也是一样的操作。 那么假设成立的话&#xff0c;就要记住我们是在树莓派&#xff08;arm&#xff09;上安装的ubuntu&#xff0c;不是X86&#xff0c;不是amd。 安装好系统后&#xff0c;我们第一…

[Linux]Ubuntu 换源 20.04 阿里源

注意&#xff0c;这篇文章其实不是简单的教你怎么换源&#xff0c;而是示例一种方法来换20.04的阿里源&#xff0c;其他源和版本大同小异。 笔者在写这篇文章的时候&#xff0c;20.04 还没有release出来正式版&#xff0c;但是已经可以在仓库里看到有源存在了&#xff0c;故写下…

Ubuntu换源详解,教你如何换源,并且解决常见的大坑

Ubuntu换源详解&#xff0c;教你如何换源&#xff0c;并且解决常见的大坑 记一次极不愉快的一次经历 首先注意&#xff0c;换源必须选择合适的版本&#xff0c;不可以在网上找一个下载源就直接去换 出现错误1&#xff1a; 由于没有公钥&#xff0c;无法验证下列签名 :NO_PUBK…

ubuntu 换源

网上应该可以找到很多关于ubuntu源的设置方法&#xff0c;但是如果不搞清楚就随便设置的话&#xff0c;不仅不能起到应有的效果&#xff0c;还会由于一些问题导致apt不可用。 最正确的更换源的方法应该如系统提示的&#xff1a; ## a.) add apt_preserve_sources_list: true …

20.04Ubuntu换源:提升软件下载速度和更新效率

在使用Ubuntu操作系统时&#xff0c;一个常见的优化措施是更改软件源&#xff0c;以提高软件下载速度和更新效率。软件源是指存储软件包的服务器&#xff0c;通过更换软件源&#xff0c;你可以选择更靠近你所在地区的服务器&#xff0c;从而加快软件下载速度&#xff0c;并减少…

Ubuntu快速更换源

Ubuntu更换源&#xff0c;零基础操作 提示&#xff1a;跟着一步步来&#xff0c;很快完成操作 为什么要换源&#xff1f;安装的linux系统默认的源是国外的&#xff0c;当用命令行安装软件&#xff08;比如安装gcc&#xff09;时下载速度非常慢&#xff0c;这里将源换成国内阿里…

Ubuntu系统换源

简单介绍一下源&#xff0c;源就是一个大仓库&#xff08;类似应用商店&#xff09;&#xff0c;系统下载软件需要从这个仓库下载&#xff0c;因为Ubuntu默认源是国外的&#xff0c;所以在下载东西的时候会出现下载速度很慢的情况&#xff0c;所以我们需要更换成国内的源&#…