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

spring bean的生命周期

作者: zhengaoly | 来源:发表于2022-03-03 09:57 被阅读0次

spring bean的生命周期

原创基础上修改,建议参考

Spring 作为当前 Java 最流行、最强大的轻量级框架,受到了程序员的热烈欢迎。准确的了解 Spring Bean 的生命周期是非常必要的。我们通常使用 ApplicationContext 作为 Spring 容器。这里,我们讲的也是 ApplicationContext 中 Bean 的生命周期。而实际上 BeanFactory 也是差不多的,只不过处理器需要手动注册。

转载请注明地址 http://www.cnblogs.com/zrtqsk/p/3735273.html

一、生命周期流程图:

Spring Bean 的完整生命周期从创建 Spring 容器开始,直到最终 Spring 容器销毁 Bean,这其中包含了一系列关键点。

img img

若容器注册了以上各种接口,程序那么将会按照以上的流程进行。下面将仔细讲解各接口作用。

二、各种接口方法分类

Bean 的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:

1、Bean 自身的方法  :  这个包括了 Bean 本身调用的方法和通过配置文件中 <bean> 的 init-method 和 destroy-method 指定的方法

2、Bean 级生命周期接口方法  :  这个包括了 BeanNameAware、BeanFactoryAware、InitializingBean 和 DiposableBean 这些接口的方法

3、容器级生命周期接口方法  :  这个包括了 InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为 “后处理器”。

4、工厂后处理器接口方法  :  这个包括了 AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer 等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。这些处理器一般处理beandifinition,因为此时bean还没有实例化.

三、演示

我们用一个简单的 Spring Bean 来演示一下 Spring Bean 的生命周期。

1、首先是一个简单的 Spring Bean,调用 Bean 自身的方法和 Bean 级生命周期接口方法,为了方便演示,它实现了 BeanNameAware、BeanFactoryAware、InitializingBean 和 DiposableBean 这 4 个接口,同时有 2 个方法,对应配置文件中@Bean的 init-method 和 destroy-method。如下:

package com.hisense.smartstation.beantest;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.io.Serializable;

/**
 * @ClassName: Student
 * @Description: TODO
 * @Create by: gaozhen
 * @Date: 2022/3/3 15:49
 */
@ConfigurationProperties(prefix = "stu")
public class Student implements Serializable, InitializingBean, DisposableBean, BeanFactoryAware, BeanNameAware {
    public Student() {
        System.out.println("Student.constructor");
    }
    @Autowired
    BirthDay birthDay;

    private String name;
    private String sex;
    private int age;
    public void init(){
        System.out.println("Student.init");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean.afterPropertiesSet");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactoryAware.setBeanFactory");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("BeanNameAware.setBeanName");
    }

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

    public String getName() {
        System.out.println("Student.getName");
        return name;
    }

    public void setName(String name) {
        System.out.println("Student.setName");
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

2、接下来是演示 BeanPostProcessor 接口的方法,如下:

package com.hisense.smartstation.beantest;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * @ClassName: StudentBeanPostProcessor
 * @Description: 初始化前后
 * @Create by: gaozhen
 * @Date: 2022/3/2 9:24
 */
@Component
public class StudentBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Student){
            System.out.println("BeanPostProcessor.postProcessBeforeInitialization");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof Student) {
            System.out.println("BeanPostProcessor.postProcessAfterInitialization");
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

如上,BeanPostProcessor 接口包括 2 个方法 postProcessAfterInitialization 和 postProcessBeforeInitialization,这两个方法的第一个参数都是要处理的 Bean 对象,第二个参数都是 Bean 的 name。返回值也都是要处理的 Bean 对象。这里要注意。

3、InstantiationAwareBeanPostProcessor 接口本质是 BeanPostProcessor 的子接口,一般我们继承 Spring 为其提供的适配器类 InstantiationAwareBeanPostProcessor Adapter 来使用它,如下:

package com.hisense.smartstation.beantest;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.stereotype.Component;

/**
 * @ClassName: StudentInstantiationBeanPostProcessor
 * @Description: InstantiationAwareBeanPostProcessorAdapter实现了InstantiationAwareBeanPostProcessor
 * 用来进行bean实例化前,后,属性注入等工作。
 * @Create by: gaozhen
 * @Date: 2022/3/3 10:37
 */
@Component
public class StudentInstantiationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
    /**
     * bean实例化之前调用
     * @param beanClass
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanClass.equals(Student.class)) {
            System.out.println("InstantiationBeanPostProcessor.BeforeInstantiation()");
        }
        return super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    /**
     * bean实例化以后调用
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (bean.getClass().equals(Student.class)) {
            System.out.println("InstantiationBeanPostProcessor.AfterInstantiation()");
        }
        return super.postProcessAfterInstantiation(bean, beanName);
    }

    /**
     * 此处可以进行依赖注入等,@autowired,@resource等注解,都是通过调用此方法进行的依赖注入
     * 相关参考:
     * @autowired使用AutowiredAnnotationBeanPostProcessor#postProcessProperties()方法
     * @resource使用CommonAnnotationBeanPostProcessor#postProcessProperties()方法
     * CommonAnnotationBeanPostProcessor进行注入,他们都是实现了InstantiationAwareBeanPostProcessor接口
     * @param pvs
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (bean.getClass()== Student.class) {
            System.out.println("InstantiationBeanPostProcessor.processProperties()");
        }

        return super.postProcessProperties(pvs, bean, beanName);
    }

    /**
     * 初始化前
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean.getClass().equals(Student.class)) {
            System.out.println("InstantiationBeanPostProcessor.BeforeInitialization()");
        }
        return super.postProcessBeforeInitialization(bean, beanName);
    }

    /**
     * 初始化后
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean.getClass().equals(Student.class)) {
            System.out.println("InstantiationBeanPostProcessor.AfterInitialization()");
        }
        return super.postProcessAfterInitialization(bean, beanName);
    }
}

这个有 3 个方法,其中第二个方法 postProcessAfterInitialization 就是重写了 BeanPostProcessor 的方法。第三个方法 postProcessPropertyValues 用来操作属性,返回值也应该是 PropertyValues 对象。

4、注入对象BirthDay

package com.hisense.smartstation.beantest;

import org.springframework.stereotype.Component;

/**
 * @ClassName: BirthDay
 * @Description: TODO
 * @Create by: gaozhen
 * @Date: 2022/3/3 14:16
 */
@Component
public class BirthDay {
    String birth = "20220303";
}

这里添加一个被注入的对象给Student,主要是为了查看BirthDay这个bean是何时被注入的,参考AutowiredAnnotationBeanPostProcessor#postProcessProperties()方法,是在Student的bean实例化以后,通过AutowiredAnnotationBeanPostProcessor#postProcessProperties()注入的,此处可添加条件断点查看.

image-20220303162602676

5、工厂后处理器接口方法BeanFactoryPostProcessor,如下:

 1 package springBeanTest;
 2 
 3 import org.springframework.beans.BeansException;
 4 import org.springframework.beans.factory.config.BeanDefinition;
 5 import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
 6 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 7 
 8 public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
 9 
10     public MyBeanFactoryPostProcessor() {
11         super();
12         System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
13     }
14 
15     @Override
16     public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
17             throws BeansException {
18         System.out
19                 .println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
20         BeanDefinition bd = arg0.getBeanDefinition("person");
21         bd.getPropertyValues().addPropertyValue("phone", "110");
22     }
23 
24 }

5、配置文件如下 beans.xml,很简单,使用 ApplicationContext, 处理器不用手动注册:

package com.hisense.smartstation.beantest;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @ClassName: StudentConfiguration
 * @Description: TODO
 * @Create by: gaozhen
 * @Date: 2022/3/3 15:56
 */
@Configuration
public class StudentConfiguration {
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Student getStudent(){
        return new Student();
    }
}

6、yml配置:

stu:
  age: 20
  name: testuser

执行结果

bean factory post processor called
InstantiationBeanPostProcessor.BeforeInstantiation()
Student.constructor
InstantiationBeanPostProcessor.AfterInstantiation()
InstantiationBeanPostProcessor.processProperties()
BeanNameAware.setBeanName
BeanFactoryAware.setBeanFactory
Student.setName
BeanPostProcessor.postProcessBeforeInitialization
InstantiationBeanPostProcessor.BeforeInitialization()
InitializingBean.afterPropertiesSet
Student.init
BeanPostProcessor.postProcessAfterInitialization
InstantiationBeanPostProcessor.AfterInitialization()
image-20220303162528850 image.png

相关文章

网友评论

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

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