• 为什么要了解Spring中 bean的生命周期?

有时候我们需要自定义bean的创建过程,因此了解Spring中 bean的生命周期非常重要。

  • 二话不说先上图:

  • 在谈具体流程之前先看看Spring官方文档中在介绍原型作用域时的一段话:In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean. The container instantiates, configures, and otherwise assembles a prototype object and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype beans hold. To get the Spring container to release resources held by prototype-scoped beans, try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up.

也就是说Spring并不会管理原型作用域对象的完整生命周期,对象在被Spring处理到上图中的“bean可以使用了”之后就脱离了spring监管,不会调用销毁方法(如果配置了),除非自定义BeanPostProcessor增加想要的销毁逻辑。

  • 接下来介绍上图中的每个步骤:
  1. Spring对bean进行实例化。
  2. Spring将值及bean的引用注入到当前bean对应的属性中。
  3. 如果bean实现了BeanNameAware接口,那么Spring将bean的ID传给setBeanName()方法。
  4. 如果bean实现了BeanFactoryAware接口,那么Spring将调用setBeanFactory()方法,同时传入BeanFactory容器实例。
  5. 如果bean实现了ApplicationContextAware接口,那么Spring将调用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将调用他的destroy()方法。类似地,如果<bean>中配置了destroy-method属性(即指定了自定义的销毁方法,和步骤7中的init-method方法一样,该方法可以抛异常但是不能有参数),则还会接着调用该方法。
  1. package com.spring.beans.cycle;
  2.  
  3. import org.springframework.beans.BeansException;
  4. import org.springframework.beans.factory.BeanFactory;
  5. import org.springframework.beans.factory.BeanFactoryAware;
  6. import org.springframework.beans.factory.BeanNameAware;
  7. import org.springframework.beans.factory.DisposableBean;
  8. import org.springframework.beans.factory.InitializingBean;
  9. import org.springframework.context.ApplicationContext;
  10. import org.springframework.context.ApplicationContextAware;
  11.  
  12. public class LolService
  13. implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware, ApplicationContextAware {
  14.  
  15. // 实现DisposableBean接口的方法
  16. @Override
  17. public void destroy() throws Exception {
  18. System.out.println("执行DisposableBean接口的destroy方法");
  19. }
  20.  
  21. // 实现InitializingBean接口的方法
  22. @Override
  23. public void afterPropertiesSet() throws Exception {
  24. System.out.println("执行InitializingBean接口的afterPropertiesSet方法");
  25. }
  26.  
  27. // 通过配置文件中<bean>的init-method属性指定的初始化方法
  28. public void init() {
  29. System.out.println("init...");
  30. }
  31.  
  32. // 通过配置文件中<bean>的destroy-method属性指定的销毁方法
  33. public void destroy0() {
  34. System.out.println("destroy0...");
  35. }
  36.  
  37. @Override
  38. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  39. System.out.println("执行ApplicationContextAware接口的setApplicationContext()方法: " + applicationContext);
  40. }
  41.  
  42. @Override
  43. public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  44. System.out.println("执行BeanFactoryAware接口的setBeanFactory()方法: " + beanFactory);
  45. }
  46.  
  47. @Override
  48. public void setBeanName(String name) {
  49. System.out.println("执行BeanNameAware接口的setBeanName()方法: " + name);
  50. }
  51.  
  52. }

示例bean:LolService

  1. package com.spring.beans.cycle;
  2.  
  3. import org.springframework.beans.BeansException;
  4. import org.springframework.beans.factory.config.BeanPostProcessor;
  5.  
  6. public class MyBeanPostProcessor implements BeanPostProcessor {
  7.  
  8. @Override
  9. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  10. System.out.println("postProcessBeforeInitialization: " + bean + ", " + beanName);
  11. return bean;
  12. }
  13.  
  14. @Override
  15. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  16. System.out.println("postProcessAfterInitialization: " + bean + ", " + beanName);
  17. return bean;
  18. }
  19.  
  20. }

BeanPostProcessor实现类

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  5.  
  6. <bean id="lolService" class="com.spring.beans.cycle.LolService" init-method="init" destroy-method="destroy0"></bean>
  7.  
  8. <bean class="com.spring.beans.cycle.MyBeanPostProcessor"></bean>
  9. </beans>

配置文件

  1. package com.spring.beans.cycle;
  2.  
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;
  4.  
  5. public class Main {
  6.  
  7. public static void main(String[] args) {
  8. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans-cycle.xml");
  9. LolService service = (LolService) context.getBean("lolService");
  10. context.close();
  11. }
  12.  
  13. }

测试类

  1. Dec 23, 2019 6:38:02 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
  2. INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@29ca901e: startup date [Mon Dec 23 18:38:02 CST 2019]; root of context hierarchy
  3. Dec 23, 2019 6:38:02 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
  4. INFO: Loading XML bean definitions from class path resource [beans-cycle.xml]
  5. 执行BeanNameAware接口的setBeanName()方法: lolService
  6. 执行BeanFactoryAware接口的setBeanFactory()方法: org.springframework.beans.factory.support.DefaultListableBeanFactory@7e0b85f9: defining beans [lolService,com.spring.beans.cycle.MyBeanPostProcessor#0]; root of factory hierarchy
  7. 执行ApplicationContextAware接口的setApplicationContext()方法: org.springframework.context.support.ClassPathXmlApplicationContext@29ca901e: startup date [Mon Dec 23 18:38:02 CST 2019]; root of context hierarchy
  8. postProcessBeforeInitialization: com.spring.beans.cycle.LolService@77847718, lolService
  9. 执行InitializingBean接口的afterPropertiesSet方法
  10. init...
  11. postProcessAfterInitialization: com.spring.beans.cycle.LolService@77847718, lolService
  12. Dec 23, 2019 6:38:03 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose
  13. INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@29ca901e: startup date [Mon Dec 23 18:38:02 CST 2019]; root of context hierarchy
  14. 执行DisposableBean接口的destroy方法
  15. destroy0...

控制台

Spring中 bean的生命周期的更多相关文章

  1. JAVA面试题:Spring中bean的生命周期

    Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一 ...

  2. 深入理解Spring中bean的生命周期

    [Spring中bean的生命周期] bean的生命周期 1.以ApplocationContext上下文单例模式装配bean为例,深入探讨bean的生命周期: (1).生命周期图: (2).具体事例 ...

  3. Spring中Bean的生命周期及其扩展点

    原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6106456.html Spring中Bean的管理是其最基本的功能,根据下面的图来了解Spr ...

  4. 简:Spring中Bean的生命周期及代码示例

    (重要:spring bean的生命周期. spring的bean周期,装配.看过spring 源码吗?(把容器启动过程说了一遍,xml解析,bean装载,bean缓存等)) 完整的生命周期概述(牢记 ...

  5. 通过BeanPostProcessor理解Spring中Bean的生命周期

    通过BeanPostProcessor理解Spring中Bean的生命周期及AOP原理 Spring源码解析(十一)Spring扩展接口InstantiationAwareBeanPostProces ...

  6. 一分钟掌握Spring中bean的生命周期!

    Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean 的别名只能维持 ...

  7. Spring中bean的生命周期!

    Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一 ...

  8. Spring官网阅读(十)Spring中Bean的生命周期(下)

    文章目录 生命周期概念补充 实例化 createBean流程分析 doCreateBean流程分析 第一步:factoryBeanInstanceCache什么时候不为空? 第二步:创建对象(crea ...

  9. 如果你每次面试前都要去背一篇Spring中Bean的生命周期,请看完这篇文章

    前言 当你准备去复习Spring中Bean的生命周期的时候,这个时候你开始上网找资料,很大概率会看到下面这张图: 先不论这张图上是否全面,但是就说这张图吧,你是不是背了又忘,忘了又背? 究其原因在于, ...

随机推荐

  1. spark-scala-java实现wordcount

    引入:spark-scala-java实现wordcount 1.spark-scala实现wordcount package com.cw.scala.spark import org.apache ...

  2. spring-boot 环境搭建(一)

    环境 jdk 8 tomcat 8.5 sts 4.4.2 maven 3.6.1 新建 maven 项目 首先创建一个普通的 maven 项目. pom.xml <project xmlns= ...

  3. 【重启C++】 关于 【类】

    1.什么是抽象类 带有纯虚函数成员的类,称为抽象类.抽象类不能被实例化,因为如果能实例化,调用这个纯虚的成员函数时怎么处理. 2.什么是纯虚函数 纯虚函数是在声明虚函数时被“初始化”为0的函数.声明纯 ...

  4. GoJS

    GoJS GoJS示例 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...

  5. 面试常考的js题目(二)

    1. 已知 fn 为一个预定义函数,实现函数 curryIt,调用之后满足如下条件: 返回一个函数 a,a 的 length 属性值为 1(即显式声明 a 接收一个参数) 调用 a 之后,返回一个函数 ...

  6. wpf 模板绑定父对象

    有两种方式可以实现在模板中元素绑定到父对象 1.<ContentPresenter Margin=”{TemplateBinding Padding}”/> 2.Color=”{Bindi ...

  7. nfs服务器的搭建和使用

    目录 更新记录 1.nfs介绍 1.1 nfs概念 1.2 nfs工作原理 1.3 nfs通讯过程 2.搭建和测试 NFS 服务器 2.1 搭建NFS服务器 2.2 测试NFS服务器 3.在线调试:N ...

  8. SSH远程连接工具汇总

    1)Xshell 常见问题: 1) 终端中的字体横向显示 字体中带有@的均为横向字体, 只要选择一个不带@的字体即可 2)putty 常见问题: 1)putty中编辑脚本,文字呈现蓝色,辨识度较差,需 ...

  9. jquery.validate.js表单验证 jquery.validate.js的用法

    jquery.validate.js这个插件已经用了2年多了,是一个不可多得的表单验证最方便快捷的插件.基于jquery的小插件,基本小白一学就会上手,对于项目表单页面比较多,元素比较多的校验,该插件 ...

  10. vue中params-解决换路由不刷新问题

    因为依赖路由的params参数获取写在created生命周期里面,因为相同路由二次甚至多次加载的关系 没有达到监听,退出页面再进入另一个文章页面并不会运行created组件生命周期,导致文章数据还是第 ...