完整的生命周期(牢记):

1.spring容器准备

2.实例化bean

3.注入依赖关系

4.初始化bean

5.使用bean

6.销毁bean

Bean的完整生命週期可以認為是從容器建立初始化Bean開始,直到Spring容器關閉。
事實上,在Bean被初始化建立之前,容器級別的介面方法也會對Bean產生影響,因此這裡把這兩個事件也加進來了。

各种接口方法分类

将上述流程分为三类:
1.Bean自身的方法,如Bean自身的构造函数、Setter方法设置属性以及<bean>的init-method和destroy-method所指定的初始化和销毁时的方法。
2.Bean级别生命周期接口方法,需要bean自身实现接口的方法,如BeanNameAware、BeanFactoryAware、InitializingBean和DisposableBean(例:如果这个Bean实现了BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,此处传递的是Spring配置文件中Bean的ID)
3.容器级别生命周期接口,即 后处理器 。此类一般不由Bean本身实现,独立于Bean,实现这些接口的类以容器附加装置的形式注册到Spring容器中。特点是:当Spring容器创建任何Bean的时候,这些后处理器都会执行并发生作用,它们的影响是全局性的。 如: InstantiationAwareBeanPostProcessor和BeanPostProcessor 接口。
后处理器在实例化bean的时候就实例化了,如BeanPostProcessor在实例化bean之前已经实例化,但在初始化bean的时候才被使用,见上图 区别:
第一类别,目标Bean关注自身方法,不需要实现任何接口。
第二类别,目标Bean需要实现相应的接口,有耦合。
第三类别,修改和目标Bean没有关系,需要额外的类实现接口,并注册到Spring容器中。
Bean生命周期   (分为BeanFactory和ApplicationContext两种情况)

Spring框架中,一旦把一个Bean纳入Spring IOC容器之中,这个Bean的生命周期就会交由容器进行管理,一般担当管理角色的是BeanFactory或者ApplicationContext

如图,ApplicationContext继承自BeanFactory,因而提供BeanFactory所有的功能,除此之外还继承了其他接口,所以

ApplicationContext包还提供了以下的功能: (链接:https://www.zhihu.com/question/38597460/answer/279813125)
1.MessageSource, 提供国际化的消息访问
2.资源访问,如URL和文件
3.事件传播
4.载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
5.其它区别
1).BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。
2).BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册

以下都是不包含(1.spring容器准备)的生命周期
 
BeanFactory中的Bean的生命周期

图中步骤编号对应生命周期:

1.spring容器准备:图中未包含

2.实例化bean:1,2,3,4

3.注入依赖关系:5,6,7

4.初始化bean:8,9,10,11

5.使用bean:12

6.销毁bean:13,14

见上图,对于prototype作用域的Bean,Spring容器仅仅负责创建,当容器创建了Bean实例之后,Bean实例完全交给客户端代码管理,容器不再跟踪其生命周期。每次客户端请求prototype作用域的Bean时,Spring都会产生一个新的实例,Spring容器无法知道它曾经创造了多少个prototype作用域的Bean,也无从知道这些prototype作用域的Bean什么时候才会销毁。因此,Spring无法管理prototype作用域的Bean。

  1. 当调用者通过getBean(beanName)向容器请求某一个Bean时,如果容器中注册了 InstantiationAwareBeanPostProcessor接口,就会在实例化Bean之前,调用接口的postProcessBeforeInstantiation()方法。
  2. 根据配置情况调用Bean构造函数或工厂方法实例化Bean
  3. 调用postProcessAfterInstantiation()方法,对已经实例化的对象进行一些加工
  4. 如果Bean配置了属性信息,这一步将配置值设置到Bean对应的属性中,在设置每个属性之前将先调用postProcessPropertyValues()方法
  5. 调用Bean的属性设置方法设置属性
  6. 如果实现了BeanNameAware接口,将调用setBeanName()接口方法,将配置文件中该Bean对应的名称设置到Bean中
  7. 如果实现了BeanFactoryAware接口,通过setBeanFactory()方法,将BeanFactory()容器实例设置到Bean
  8. 如果BeanFactory装配了BeanPostProcessor后处理器,将调用Object postProcessBeforeInitialization(Object bean,String beanName)接口方法对Bean进行加工操作。bean为当前正在处理的Bean,返回加工后的Bean。为容器提供对Bean进行后续加工处理的切入点,AOP,动态代理等功能都是通过BeanPostProcessor实施的。
  9. 如果Bean实现了InitializingBean接口,将调用接口的afterPropertiesSet()方法
  10. 执行<bean>中init-method属性定义的初始化方法
  11. BeanPostProcessor后处理器的 postProcessAfterInitialization再次对bean进行加工
  12. 如果scope='prototype',就返回bean给调用者,调用者负责bean后续生命的管理,Spring不再管理这个Bean的生命周期。如果作用范围是"singleton",Bean将放入SpringIoC容器缓存池中,并将bean引用返回,Spring继续对这些Bean进行后续的生命管理。
  13. 对于singleton的bean,容器关闭时会触发Spring对Bean后续生命周期的管理。如果Bean实现了DisposableBean接口,将调用接口的destory()方法,可以在此编写释放资源,记录日志等操作。(dispose处理)
  14. 调用<bean>的destroy-method属性指定的方法进行bean的销毁
 
Bean的完整生命周期从Spring容器实例化开始,直到最终销毁Bean。大致分为4类操作:
  • Bean自身的方法:如调用Bean构造函数实例化Bean,调用Setter设置Bean的属性值及通过<bean>的init-method和destroy-method所指定的方法
  • Bean级生命周期接口方法:BeanNameAware,BeanFactoryAware,InitializingBean和DisposableBean,接口方法由Bean类直接实现
  • 容器级生命周期接口:InstantiationAwareBeanPostProcesser和BeanPostProcessor这两个接口实现,一般称为"后处理器"。实现类以容器附加装置的形式注册到Spring容器中,通过接口反射为Spring容器扫描识别。Spring容器创建任何Bean时,这些后处理器都会发生作用,影响是全局性的。
  • 工厂后处理器接口方法:AspectJWeavingEnabler,CustomAutowireConfigurer,ConfigurationClassPostProcessor等方法。容器级,在应用上下文装配配置文件后立即调用。
 
Bean级生命周期接口处理Bean个性化的问题
容器级生命周期接口处理Bean共性化的问题
InstantiationAwareBeanPostProcessor其实是BeanPostProcessor接口的子接口,Spring为其提供了一个适配器类InstantiationAwareBeanPostProcessorAdapter,可以方便的扩展该类。
 
main():手动注册
ResourceLoader resourceLoader = new PathMatchingResourcePatternResolver();
Resource resource = resourceLoader.getResource("classpath:spring/SpringContext.xml"); BeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory) beanFactory);
reader.loadBeanDefinitions(resource); //向容器中注册BeanPostProcessor后处理器
((ConfigurableBeanFactory) beanFactory).addBeanPostProcessor(new MyBeanPostProcessor());
((ConfigurableBeanFactory) beanFactory).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor()); Car car = (Car) beanFactory.getBean("car");
Car car1 = (Car) beanFactory.getBean("car");
System.out.println(car == car1);//默认单例,两次获取的car对象一样
car.carRun(); //关闭容器
((DefaultListableBeanFactory) beanFactory).destroySingletons();
 在对beanfactory注册BeanPostProcessor后处理器时,将beanfactory强制类型转换为了ConfigurableBeanFactory。由于addBeanPostProcessor()方法是在ConfigurableBeanFactory接口中定义的。多个后处理器注册时,实际调用顺序和注册顺序无关,多后处理器需要实现Ordered接口。
    
    上面获取了两次car对象,如果是prototype范围,则生命周期会被执行两次,因为每次都返回的新对象实例。
思考:
    通过Bean级别的生命周期接口对Bean进行控制,虽然让Bean具有了更细致的生命周期阶段,但是让Bean和Spring框架紧密结合在一起了。通常通过init-method和destroy-method属性配置的方式来为Bean指定初始化和销毁的方法。
    Spring还提供了一个Bean后置处理器,InitDestroyAnnotationBeanPostProcessor.负责对标注了@PostConstruct,@PreDestroy的Bean进行处理,在bean初始化后及销毁前执行相应的逻辑(在ApplicationContext中,已经默认装配了该处理器)。
    如果bean希望在运行期获知在配置文件中的Bean名称,可以简单地将名称作为属性注入
    BeanProcessor接口十分特殊,它不要求Bean去继承,可以完全像插件一样注册到Spring容器中。AOP等功能就是基于此实现的。    
 
ApplicationContext中Bean的生命周期  

Bean在应用上下文中的生命周期和在BeanFactory中的生命周期类似,不同的是,如果Bean实现了org.springframework.context.ApplicationContextAware接口,则会增加一个调用方法setApplicationContext()的步骤。

 
      如果配置文件中声明了工厂后处理器接口BeanFactoryPostProcessor的实现类,在初始化Bean实例之前会调用这些BeanFactoryPostProcessor对配置信息进行加工处理。Spring框架提供了多个工厂后处理器,CustomEditorConfigurer,PopertyPlaceholderConfigurer等。
                 工厂后处理器是容器级的,仅在应用上下文初始化时调用一次,目的是完成一些配置文件的加工处理工作。
     
     
ApplicationContext Bean生命周期流程:

(总结:)

初始化阶段,先调用 InitializingBean接口的afterPropertiesSet()方法,再调用init-method属性定义的初始化方法。与销毁阶段不同的是,初始化阶段外面包裹了一层BeanPostProcessor后处理器的postProcessBeforeInitialization()和postProcessAfterInitialization()方法

销毁阶段,先调用 DisposableBean接口的destory()方法,再调用destory-method属性定义的销毁方法

BeanFactory和ApplicationContext区别就在于BeanFactory手动注册:

ApplicationContext会利用Java反射机制自动识别出配置文件中定义的BeanPostProcesser,InstantiationAwareBeanPostProcessor和BeanFactoryPostProcessor,并自动将它们注册到应用上下文中。而BeanFactory需要手动addBeanPostProcessor()去进行注册。

调用ApplicationContextAware接口的setApplicationContext()方法,传入该BeanApplicationContext,这样该Bean就获得了自己所在的ApplicationContext,不用再手动注册了

            ApplicationContext Bean生命周期流程

流程

 
                BeanFactory Bean生命周期流程
 
 
代码示例见另一篇:https://i.cnblogs.com/EditPosts.aspx?postid=10215041&update=1
 
 
 https://super-wangj.iteye.com/blog/2386440
http://lvsongsong.top/article/html/94f196c8978243c6905ca5267cf20663
https://zsr.github.io/2017/05/05/Spring-Bean-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/

【不懂】spring bean生命周期的更多相关文章

  1. spring bean 生命周期和 ? 作用域? spirng bean 相互依赖? jvm oom ? jvm 监控工具? ThreadLocal 原理

    1. spring bean 生命周期 1. 实例化一个bean ,即new 2. 初始化bean 的属性 3. 如果实现接口 BeanNameAware ,调用 setBeanName 4. Bea ...

  2. Spring点滴四:Spring Bean生命周期

    Spring Bean 生命周期示意图: 了解Spring的生命周期非常重要,我们可以利用Spring机制来定制Bean的实例化过程. -------------------------------- ...

  3. Spring Bean 生命周期之destroy——终极信仰

    上一篇文章 Spring Bean 生命周期之我从哪里来 说明了我是谁? 和 我从哪里来? 的两大哲学问题,今天我们要讨论一下终极哲学我要到哪里去? 初始化 Spring Bean 有三种方式: @P ...

  4. 常见问题:Web/Servlet生命周期与Spring Bean生命周期

    Servlet生命周期 init()初始化阶段 Servlet容器加载Servlet(web.xml中有load-on-startup=1;Servlet容器启动后用户首次向Servlet发请求;Se ...

  5. 大厂高频面试题Spring Bean生命周期最详解

    Spring作为当前Java最流行.最强大的轻量级框架.Spring Bean的生命周期也是面试高频题,了解Spring Bean周期也能更好地帮助我们解决日常开发中的问题.程序员应该都知道Sprin ...

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

    大家好,我是老三,上节我们手撸了一个简单的IOC容器五分钟,手撸一个Spring容器!,这节我们来看一看Spring中Bean的生命周期,我发现,和人的一生真的很像. 简单说说IoC和Bean IoC ...

  7. 睡前聊一聊"spring bean 生命周期"

    spring bean 生命周期=实属初销+2个常见接口+3个Aware型接口+2个生命周期接口 实属初销:spring bean生命周期只有四个阶段,即实例化->属性赋值->初始化-&g ...

  8. Spring Bean 生命周期2

    在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一个实例,而不是每次都产生一个新的对象使用Sin ...

  9. Spring bean 生命周期验证

    一.从源码注释看bean生命周期 从JDK源码上看,BeanFactory实现类需要支持Bean的完整生命周期,完整的初始化方法及其标准顺序(格式:接口 方法)为: 1.BeanNameAware s ...

随机推荐

  1. Gym - 101848C Object-Oriented Programming (树链剖分+线段树+动态开点)

    C. Object-Oriented Programming time limit per test 3.0 s memory limit per test 1024 MB input standar ...

  2. 网络流相关知识点以及题目//POJ1273 POJ 3436 POJ2112 POJ 1149

    首先来认识一下网络流中最大流的问题 给定一个有向图G=(V,E),把图中的边看做成管道,边权看做成每根管道能通过的最大流量(容量),给定源点s和汇点t,在源点有一个水源,在汇点有一个蓄水池,问s-t的 ...

  3. 利用SSH上传、下载(使用sz与rz命令)

    安装yum -y install lrzsz 用法sz用法:从服务器发送出去相当于下载一个文件sz filename 下载多个文件sz filename1 filename2rz用法:从外面接收回来, ...

  4. UOJ277【清华集训2016】定向越野(计算几何,最短路)

    UOJ题目传送门 显然最优的路径只会经过若干条两个圆的公切线和若干段圆弧 为了方便,把起点终点看成两个半径为\(0\)的圆也行. 最烦的就是算两个圆的公切线了,一共有四条 对于靠外面的两条,我们把切线 ...

  5. Coding and Paper Letter(五十八)

    资源整理. 1 Coding: 1.支持TMS.WMTS标准瓦片下载,支持百度地图瓦片.高德地图瓦片.腾讯地图瓦片.天地图.ArcServer Rest瓦片.ArcServer本地缓存切片.geose ...

  6. Hdoj 2084.数塔 题解

    Problem Description 在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的: 有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大 ...

  7. 如何查看Linux操作系统版本?

    参考地址:http://www.ggat.cn/newsInfo.html/71 如何查看Linux操作系统版本? 1. 查看内核版本命令: $ cat /proc/version $ uname - ...

  8. [SCOI2015]国旗计划[Wf2014]Surveillance

    [SCOI2015]国旗计划 A国正在开展一项伟大的计划——国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这 项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了N名 ...

  9. 解决关于confluence缓慢 字体乱码 宏乱码 编辑不能贴图等问题

    应用场景:Confluence软件不用多说,与Jira一样,都是atlassion的精品软件,不再介绍. 这里因为使用的是破解版的confluence,故遇见一些问题,只能百度谷歌自行解决,也在此记录 ...

  10. 如何在Windows 10上运行Docker和Kubernetes?

    如何在Windows 10上运行Docker和Kubernetes? 在Windows上学习Docker和Kubernetes,开始的时候会让你觉得无从下手.最起码安装好这些软件都不是一件容易的事情. ...