spring bean的生命周期

bean的生命周期

bean的生命周期指bean从创建到最终销毁要经历的阶段,简单来看,spring中bean的生命周期分为下面几个步骤。

青铜版

通过代码演示spring bean的生命周期:

public class Monkey  {

    private String nickname;
    
    public Monkey() {
        System.out.println("1.创建对象");
    }

    @Value("wukong")
    public void setNickname(String nickname) {
        System.out.println("2.设置属性");
        this.nickname = nickname;
    }

    public void init() {
        System.out.println("3.初始化方法");
    }

    public void myDestroy() {
        System.out.println("5.销毁方法");
    }

}

创建Monkey配置类将对象放入容器

@Configuration
@ComponentScan(basePackages = "com.monkey1024")
public class MonkeyConfiguration {
    
    //将对象放入容器并指定init和destroy方法
    @Bean(name = "monkey",initMethod = "init",destroyMethod = "myDestroy")
    public Monkey monkeyInstance() {
        return new Monkey();
    }
}

创建测试代码,执行后可以看到对应的打印结果

//通过注解创建容器对象
ApplicationContext context = new AnnotationConfigApplicationContext(MonkeyConfiguration.class);

Monkey monkey = context.getBean("monkey", Monkey.class);
System.out.println("4.使用:" + monkey);

((AnnotationConfigApplicationContext) context).close();

bean的生命周期之BeanPostProcessor接口

在青铜版的生命周期之间,spring提供了一些钩子(hook),我们可以利用钩子在bean生命周期的某个阶段实现特定的需求。例如可以利用BeanPostProcessor接口在bean初始化前后做一些操作,该接口的实现类被称为bean后处理器。

spring bean生命周期的白银版本:

创建一个类实现BeanPostProcessor接口,并重写2个方法:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行before:" + bean + "===" + beanName);
        //这里要将bean返回
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        System.out.println("执行after:" + bean + "===" + beanName);

        return bean;
    }
}

测试代码同上,运行之后观察打印结果

bean的生命周期之InstantiationAwareBeanPostProcessor接口

spring在该接口中提供了钩子,我们可以利用这些钩子在bean对象创建之前和之后做一些事情。

spring bean生命周期的黄金版

创建实现类

@Component
public class MyInstantiationProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("执行InstantiationAwareBeanPostProcessor的before方法");
        //若返回非null,则不会执行初始化和BeanPostProcessor中的方法
        return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("执行InstantiationAwareBeanPostProcessor的after方法");
        //若返回false,则不会注入bean中的属性
        return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
    }
    
}

测试代码同上,运行观察结果。

bean的生命周期之其他接口

Aware相关接口

从使用上来看,spring中的对象分为自定义对象和容器对象。若在自定义对象中获取容器对象时就会用到aware相关接口,spring会调用对应的set方法传入容器对象。比如自己定义了一个Monkey类,可以利用aware的子类来获取ApplicationContext对象。

//实现ApplicationContextAware
public class Monkey implements ApplicationContextAware {
    private String nickname;

    private ApplicationContext applicationContext;

    
    //spring会调用该方法将applicationContext对象传入
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

InitializingBean接口

该接口中只有1个方法,会在BeanPostProcessor中的before之后,初始化方法之前执行。

DisposableBean接口

该接口只有1个方法,会在使用之后,销毁方法之前执行。

bean生命周期之铂金版

修改Monkey类如下:

public class Monkey implements ApplicationContextAware, InitializingBean, DisposableBean {

    private String nickname;

    public Monkey() {
        System.out.println("1.创建对象");
    }

    @Value("wukong")
    public void setNickname(String nickname) {
        System.out.println("2.设置属性");
        this.nickname = nickname;
    }

    public void init() {
        System.out.println("3.初始化方法");
    }

    public void myDestroy() {
        System.out.println("5.销毁方法");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContextAware");
    }

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

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

}

运行之前的测试代码观察结果。