zoukankan      html  css  js  c++  java
  • 【不懂】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/
  • 相关阅读:
    5.8 Properties
    5.7(java学习笔记)Vector、Enumeration
    5.6(java学习笔记) queue
    5.5(java学习笔记)TreeSet和TreeMap
    5.4 (Java学习笔记)集合的排序(Collections.sort(),及Arrays.sort())
    UBUNTU18.04安装使用ORB-SLAM2
    UBUNTU18.04安装CUDA
    UBUNTU18.04安装Pangolin
    ubuntu18.08安装eigen
    Ubuntu18.4安装g2o
  • 原文地址:https://www.cnblogs.com/twoheads/p/10233440.html
Copyright © 2011-2022 走看看