• SpringBean的生命周期


    一步一步,带你了解SpringBean的生命周期

    推荐阅读:

    1. Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC
    2. 一个SpringBoot问题就干趴下了?我却凭着这份PDF文档吊打面试官.

    SpringBean的生命周期

    在面试中,我们经常会被问到一个问题,就是SpringBean的生命周期。用大白话说,就是说其在创造到销毁按顺序调用了什么方法,在我刚开始学了,一般就是对着标准答案去硬背,完全不了解其意思,也十分容易忘记。

    流程图如下

    一步一步,带你了解SpringBean的生命周期

     

    这样看上去十分的复杂,记住也很容易忘掉。

    所以,我下面会用代码的方式一步步来模拟SpringBean的工作流程,做到深入了解,这样就不会再次忘记这个知识点了。

    既然都说Bean对象Bean对象,那么SpringBean自然也是一个对象了,我们用一个简单的对象来说明,那么要创建对象就需要有构造方法,对象还会有它的属性跟get、set方法。

     private String field;
    
     public SpringBean() {
     System.out.println("SpringBean 构造方法");
     }
    
     public String getField() {
     System.out.println("SpringBean get方法");
     return field;
     }
    
     public void setField(String field) {
     System.out.println("SpringBean set方法");
     this.field = field;
     }

    众所周知要创建一个SpringBean的话还要在配置文件里去声明这个Beam,当然也可以用注解的方式。

     <bean class="SpringBean">
    	 <property name="field" value="test" />
     </bean>

    然后我们去初始化这个容器看看,运行结果是什么

    public static void main(String[] args) {
     ClassPathXmlApplicationContext applicationContext =
     new ClassPathXmlApplicationContext("spring.xml");
     }
    一步一步,带你了解SpringBean的生命周期

     

    这里我们可以看到当我们在容器里面加载bean的时候,它会依次调用构造方法和set方法,这两步我相信大部分人都知道。但是除此之外我们想一想,我们的Spring它是否还干了别的事情,我们接下来看一下。

    如果这个Bean它实现了一些Aware接口的话,它就会注入和bean容器基础属性层面相关的信息。比如实现了BeanNameAware接口,我们要重写它的setBeanName方法,在配置文件中把这个Bean的id设置一下

     public void setBeanName(String s) {
     System.out.println("setBeanName:"+s);
     }
    <bean id="BeanName" class="SpringBean">
    	 <property name="field" value="test" />
     </bean>

    运行一下看会发生什么

    一步一步,带你了解SpringBean的生命周期

     

    剩下的BeanFactoryAware和ApplicationContextAware接口同理,我们直接看结果

    一步一步,带你了解SpringBean的生命周期

     

    我们可以看到先执行的是setBeanFactory方法然后是setApplicationContext方法

    下面我们再创建一个新的Bean,这个Bean是做全局的前置和后置初始化的,也就是我们看面试题时所说的前置处理器和后置处理器。

    这个Bean我们实现BeanPostProcessor接口

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
     System.out.println("postProcessBeforeInitialization");
     return bean;
     }
    
     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
     System.out.println("postProcessAfterInitialization");
     return null;
     }

    千万不要忘记要在配置文件里声明这个Bean

    <bean class="SpringProccesserBean"></bean>

    然后我们再运行试试

    一步一步,带你了解SpringBean的生命周期

     

    不出我们所料,前置方法和后置方法依次在后面运行了,难道这就是Bean的全部了吗?呵呵,太天真了,如果在Bean中有实现InitializingBean接口,那又是不同的说法了。我们下面除了重写了afterPropertiesSet方法以外我们还可以在bean里面指定它的init方法。

     public void afterPropertiesSet() throws Exception {
     System.out.println("afterPropertiesSet");
     }
    
     public void init(){
     System.out.println("init");
     }

    不要忘记配置文件

    <bean id="BeanName" class="SpringBean" init-method="init">
    	 <property name="field" value="test" />
     </bean>
    一步一步,带你了解SpringBean的生命周期

     

    可以看到,这两个方法是夹在前置处理器和后置处理器之间的,先执行的是InitializingBean接口的afterPropertiesSet方法然后是Bean自身的init方法。

    至此,一个Bean的初始化环节就完成了,我们就可以去使用这个Bean了。

    既然是说Bean的生命周期,那当然还有Bean的销毁流程了,Bean的销毁流程一共分为连个步骤,一个步骤是实现销毁接口DisposableBean,重写它的销毁方法destroy,还有一个是Bean自身的destroy方法。

    public void destroy() throws Exception {
     System.out.println("DisposableBean");
     }
    
    public void des(){
     System.out.println("des");
     }

    记得要在配置文件里定义

    <bean id="BeanName" class="SpringBean" init-method="init" destroy-method="des">
    	 <property name="field" value="test" />
     </bean>

    这两个方法会在关闭容易的时候调用,因此我们调用close方法关闭容器

    public static void main(String[] args) {
     ClassPathXmlApplicationContext applicationContext =
     new ClassPathXmlApplicationContext("spring.xml");
    
     applicationContext.close();
    
     }

    运行结果

    一步一步,带你了解SpringBean的生命周期

     

    我们看到是先调用DisposableBean接口的destroy方法然后是Bean自身的销毁方法。

    这就是SpringBean的生命周期。

    下面我们来总结一下

    Spring Bean的生命周期

     1、实例化Bean对象
     2、设置Bean属性
     3、如果通过各种Aware接口声明了依赖关系,则会注入Bean对容器基础设施层面的依赖。
     Aware接口集体包括BeanNameAware、BeanFactoryAware和ApplicationContextAware
     分别注入Bean ID、Bean Factory 和ApplicationContext
     4、如果实现了BeanPostProcesser,调用BeanPostProcesser的前置初始化方法postProcessBeforeInitialization
     5、如果实现了InitializingBean接口,则会调用afterPropertiesSet方法
     6、调用Bean自身定义的init方法
     7、调用BeanPostProcesser的后置方法postProcessAfterInitialization
     创建完毕
     销毁
     8、容器关闭前调用DisposableBean的destroy方法和自身的destroy方法
    JUST DO IT!
  • 相关阅读:
    剑指offer-二叉树的深度
    剑指offer-二叉树中和为某一值的路径
    剑指offer-数组中只出现一次的数字
    剑指offer-反转单词顺序列
    剑指offer-数字在排序数组中出现的次数
    剑指offer-第一个只出现一次的字符
    剑指offer-连续子数组的最大和
    剑指offer-数组中的逆序对
    CSS3滚动条美化,CSS3滚动条皮肤
    mouseover事件与mouseenter事件的区别
  • 原文地址:https://www.cnblogs.com/caicz/p/15080025.html
Copyright © 2020-2023  润新知