bean的生命周期详解

bean的生命周期详解

文章内容引用自 咕泡科技 咕泡出品,必属精品

原文链接:Bean的生命周期(不要背了记思想) - 腾讯云开发者社区-腾讯云 (tencent.com)

学前必看

  没有前置知识盲目的去学习 Bean 的生命周期,是没有任何意义的,或者说这只是为了应付面试而学,没有使用场景,没有复习欲望,看完背完你能记多久呢? 一周?一个月? 你大学学的计算机网络你还记得吗?😆

  在学习 Bean 的生命周期之前,你至少应该知道,或者至少了解 Spring IOC 和 DI 以及他们的详细流程、Spring 容器的初始化流程、AOP 的代码织入过程等,有兴趣的还可以学习一下 Spring 是如何解决循环依赖的,以及 Spring 中的一些其他经典代码。等学习完上述知识之后,你就已经对 Spring 有了一个基本还算完善的概念,这时你也知道了一个 Bean 在容器初始化的时候经历了什么,然后再去系统地学习 Bean 完整的生命流程,对照先前学习的知识,查漏补缺。

Tips

  • 学习 Spring 和看 Spring 源码前一定要先学思想!!!

  • 学习 Spring 和看 Spring 源码前一定要先学思想!!!

  • 学习 Spring 和看 Spring 源码前一定要先学思想!!!

 

创建 bean 的过程

你若是真的为面试而来,请把下面这段背下来,应付面试足矣

  简单来说,bean 的生命周期其实指的就是 Spring 创建 bean 的一个过程。这个过程并不复杂,主要有以下四个步骤:实例化、属性注入、初始化,以及最后的销毁。但是对于一些复杂 (例如依赖关系比较复杂) 的 bean ,其创建可能会多一些步骤,因为现实情况中 Spring 会在 bean 的生命周期中开放很多的接口,让我们加载 bean 的时候对 bean 做一些自定义操作 (不过通常情况下我们是用不到的)。

 

   所以在 Spring 中可能有一些特殊的 bean 介入会到其他 bean 的生命周期当中,因此,一个 bean 的完整的生命周期总共有以下几步:

 

  1. 实现了 BeanFactoryPostProcessor 接口的 bean,在加载其他的 bean 的时候,会同时调用 bean 的 postProcessBeanFactory 方法为 bean 的属性赋值、设置年龄、初始化 i18 等等。

  2. 实现了 InstantiationAwareBeanPostProcessor 接口的 bean,会在实例化 bean 之前调用 postProcessBeforeInstantiation 方法

  3. 然后对 bean 进行实例化

  4. 对 bean 进行属性注入

  5. 对 bean 进行初始化,在初始化中,又包含了以下几个小步骤:

    1. 实现了 BeanFactoryAware 接口,会先调用 setBeanFactory 方法
    2. 实现了 BeanNameAware 接口,会先调用 setBeanName 方法
    3. 实现了 BeanPostProcessor 接口,会先调用 postProcessBeforeInitialization 方法
    4. 实现了 InitializingBean 接口,会调用 afterPropertiesSet 方法
    5. 然后在进行 AOP 后置处理,通过实现 BeanPostProcessor 接口,在 postProcessAfterInitialization 方法中进行动态代理
  6. 销毁 bean

 

  这里给出一个可以让你们去跟源码一步一步看着点下去的无敌图,悄悄说一句,其实学习 Bean 的生命周期有这个图就足够了,说多了都是虚的。

Bean最长的生命周期

 

本图来自咕泡学院文泰老师,转发请注明出处,否则必究 咕泡出品,必属精品

 

bean 的完整生命周期

  在传统的 Java 应用中,bean的生命周期非常简单命了,使用 Java 关键字 new 进行Bean 的实例化后,该Bean 就能够使用了。一旦 bean 不再被使用,则由 Java 的 GC 自动进行垃圾回收。

  相比之下,Spring 管理 Bean 的生命周期就复杂多了,因为在 Spring 管理下的 bean 的生命周期其可扩展性非常强,正确理解它对我们学习和了解 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 声明销毁方法,该方法也会被调用。

 

  上面是 Spring 中 Bean 的核心接口和生命周期,面试回答上述这些已经足够了。但是翻阅 JavaDoc 文档发现除了以上接口外,还有初始化过程涉及的接口,摘自org.springframework.beans.factory.BeanFactory, 全部相关接口如下 (上述已有的就不用着重标注,把额外的相关接口着重标注下):

关于Bean的完整生命周期的其他接口

解释一下上图的一些相关过程:

  • BeanNameAware.setBeanName(): 在创建此 bean 的 bean 工厂中设置 bean 的名称,在普通属性设置之后调用,在 InitializinngBean.afterPropertiesSet() 方法之前调用
  • BeanClassLoaderAware.setBeanClassLoader(): 在普通属性设置之后,InitializingBean.afterPropertiesSet() 之前调用
  • BeanFactoryAware.setBeanFactory(): 回调提供了自己的 bean 实例工厂,在普通属性设置之后,在InitializingBean.afterPropertiesSet() 或者自定义初始化方法之前调用
  • EnvironmentAware.setEnvironment(): 设置 environment 在组件使用时调用
  • EmbeddedValueResolverAware.setEmbeddedValueResolver(): 设置 StringValueResolver 用来解决嵌入式的值域问题
  • ResourceLoaderAware.setResourceLoader(): 在普通 bean 对象之后调用,在 afterPropertiesSet 或者自定义的 init-method 之前调用,在 ApplicationContextAware 之前调用。
  • ApplicationEventPublisherAware.setApplicationEventPublisher(): 在普通 bean 属性之后调用,在初始化调用 afterPropertiesSet 或者自定义初始化方法之前调用。在 ApplicationContextAware 之前调用。
  • MessageSourceAware.setMessageSource(): 在普通 bean 属性之后调用,在初始化调用 afterPropertiesSet 或者自定义初始化方法之前调用,在 ApplicationContextAware 之前调用。
  • ApplicationContextAware.setApplicationContext(): 在普通 Bean 对象生成之后调用,在InitializingBean.afterPropertiesSet 之前调用或者用户自定义初始化方法之前。在ResourceLoaderAware.setResourceLoaderApplicationEventPublisherAware.setApplicationEventPublisherMessageSourceAware之后调用。
  • ServletContextAware.setServletContext(): 运行时设置 ServletContext,在普通 bean 初始化后调用,在InitializingBean.afterPropertiesSet 之前调用,在 ApplicationContextAware 之后调用 (注:是在WebApplicationContext 运行时)
  • BeanPostProcessor.postProcessBeforeInitialization() : 将此 BeanPostProcessor 应用于给定的新 bean 实例 在任何 bean 初始化回调方法 (像是 InitializingBean.afterPropertiesSet 或者自定义的初始化方法) 之前调用。这个 bean 将要准备填充属性的值。返回的 bean 实例可能被普通对象包装,默认实现返回是一个bean。
  • BeanPostProcessor.postProcessAfterInitialization() : 将此 BeanPostProcessor 应用于给定的新 bean实例 在任何 bean 初始化回调方法 (像是 InitializingBean.afterPropertiesSet 或者自定义的初始化方法) 之后调用。这个 bean 将要准备填充属性的值。返回的 bean 实例可能被普通对象包装
  • InitializingBean.afterPropertiesSet(): 被 BeanFactory 在设置所有 bean 属性之后调用(并且满足BeanFactory 和 ApplicationContextAware)。
  • DestructionAwareBeanPostProcessor.postProcessBeforeDestruction(): 在销毁之前将此BeanPostProcessor 应用于给定的 bean 实例。能够调用自定义回调,像是 DisposableBean 的销毁和自定义销毁方法,这个回调仅仅适用于工厂中的单例 bean (包括内部 bean)
  • 实现了自定义的 destory() 方法

 

原文链接:Bean的生命周期(不要背了记思想) - 腾讯云开发者社区-腾讯云 (tencent.com)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值