美文网首页
spring----bean生命周期的探索

spring----bean生命周期的探索

作者: 不过意局bugyj | 来源:发表于2019-09-28 16:38 被阅读0次

    bean的生命周期是面试题中出现频率很高的一题,以前总是靠死记硬背来记住(毕竟在对bean的使用中这些操作很少),现在才尝试着用代码一试。

    直接上代码:

    xml配置bean:

            <bean id="person" class="bean.Person" init-method="initMethod" destroy-method="destroyMethod">
                <property name="name" value="hsw"/>
                <property name="age" value="12"/>
            </bean>
    

    这里只配置了属性的值和init-method以及destroy-method两个方法。

    bean的类代码:

    @ToString
    public class Person implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, DisposableBean, InitializingBean {
    
       private String name;
       private int age;
    
       public Person() {
          System.out.println("无参构造函数!");
       }
    
       public String getName() {
          return name;
       }
    
       public void setName(String name) {
          System.out.println("setter begin!");
          this.name = name;
       }
    
       public int getAge() {
          return age;
       }
    
       public void setAge(int age) {
          System.out.println("setter begin!");
          this.age = age;
       }
    
       public String getBeanName() {
          return beanName;
       }
    
       public BeanFactory getBeanFactory() {
          return beanFactory;
       }
    
       private String beanName;
       private BeanFactory beanFactory;
       private ApplicationContext applicationContext;
    
       @Override
       public void setBeanName(String s) {
          System.out.println("beanNameAware");
          this.beanName = s;
       }
    
       @Override
       public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
          System.out.println("beanFactoryAware");
          this.beanFactory = beanFactory;
       }
    
       @Override
       public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
          System.out.println("applicationContextAware");
          this.applicationContext = applicationContext;
       }
    
       private void initMethod() {
          System.out.println("init-method");
       }
    
       private void destroyMethod() {
          System.out.println("destroy-method");
       }
    
       @Override
       public void afterPropertiesSet() throws Exception {
          System.out.println("InitializingBean afterPropertiesSet");
       }
    
       @Override
       public void destroy() throws Exception {
          System.out.println("Disposable destroy");
       }
    }
    

    可以看到bean实现的方法有很多,首先是xxxAware三个接口,能让bean察觉到spring容器存在的三个接口。然后就是两个非方法对应xml配置中的两个配置:initMethod、destroyMethod。最后就是实现了InitializingBean 的 afterPropertiesSet 方法和 Disposable 的 destroy 方法。这些方法都会在bean的生命周期中被调用以实现一些自定义的功能。

    PostProcessor即bean的后处理器

    自定义InstantiationAwareBeanPostProcessor:

    public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            System.out.println("postProcessBeforeInstantiation");
            return null;
        }
    
        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
            System.out.println("postProcessProperties");
            return null;
        }
    
        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessAfterInstantiation");
            return true;
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessBeforeInitialization");
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("postProcessAfterInitialization");
            return bean;
        }
    }
    

    在xml文件中配置一下:

    <bean id="myInstantiationAwareBeanPostProcessor" class="others.MyInstantiationAwareBeanPostProcessor"/>
    

    这里有必要说一下:此自定义类命名为MyInstantiationBeanPostProcessor,实现了InstantiationAwareBeanPostProcessor 的几个方法。意思是对实例化阶段处理。但却多出了与接口不太相符的初始化方法,这是因为InstantiationAwareBeanPostProcessor的父接口是BeanPostProcessor,这个接口有两个默认自定义类的接口没有实现(postProcessBeforeInitialization 和 postProcessAfterInitialization),我直接在自定义类中实现了(当然也可以自己自定义一个如MyInitialazation...自定义类实现)。

    测试方法:

        @Test
        public void testOne() {
            ClassPathXmlApplicationContext context
                    = new ClassPathXmlApplicationContext("/bean.xml");
            Person person = (Person) context.getBean("person");
            System.out.println(person);
            context.close();
        }
    

    启动容器获取bean打印后关闭容器。

    运行结果:

    postProcessBeforeInstantiation
    无参构造函数!
    postProcessAfterInstantiation
    postProcessProperties
    setter begin!
    setter begin!
    beanNameAware
    beanFactoryAware
    applicationContextAware
    postProcessBeforeInitialization
    InitializingBean afterPropertiesSet
    init-method
    postProcessAfterInitialization
    Person(...)//person信息,这里略
    Disposable destroy
    destroy-method
    

    流程梳理

    所以根据输出结果可以得出bean的生命周期大致为:

    1. InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation,顾名思义实例化之前调用,方法有两个参数,bean所属class对象和beanName,返回Object对象。
    2. 实例化,配置时使用的是set注入属性,所以这里调用无参构造方法。如果使用的是有参构造方法就不会了。
    3. InstantiationAwareBeanPostProcessor 的 postProcessAfterInstantiation,顾名思义实例化之后调用,方法依旧两个参数:Object bean, String beanName,返回boolean。

    这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。如果该方法返回false,会忽略属性值的设置;如果返回true,会按照正常流程设置属性值

    1. InstantiationAwareBeanPostProcessor 的 postProcessProperties 。

    方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法不会被调用。可以在该方法内对属性值进行修改

    1. 开始调用bean的setter方法注入配置的属性值。
    2. 注入配置好的aware接口的属性。
    3. BeanPostProcessor 的 postProcessBeforeInitialization方法,即调用初始化方法前进行相关处理,方法参数同样为Object bean, String beanName,返回Object对象。这里可以返回已经初始化好了bean,也可以返回包装后的bean,甚至其他bean。
    4. bean实现的接口InitializingBean 的 afterPropertiesSet方法,无参数无返回值,但在bean内部可以访问bean的相关属性。
    5. 然后就是init-method方法了,无参数无返回值,在bean内部。
    6. BeanPostProcessor 的 PostProcessAfterInitialation方法,参数返回值和before相同。
    7. 至此相关作用域获取到bean,这里是打印了bean的信息。如果是原型模式,bean的生命周期随其作用域。如果配置的是单例,则由spring容器管理,后面容器关闭时会有后续过程。
    8. 调用DisposableBean 的 destroy 方法, 无参数无返回值。
    9. 调用xml文件配置的destroy-method。

    相关文章

      网友评论

          本文标题:spring----bean生命周期的探索

          本文链接:https://www.haomeiwen.com/subject/qmctpctx.html