【不懂】spring bean生命周期

 

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

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属性定义的销毁方法

 

BeanFactoryApplicationContext区别就在于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/
posted @ 2019-01-07 15:18  twoheads  阅读(406)  评论(0编辑  收藏  举报