4.Spring5底层原理之Bean的生命周期

这一节我们学习Bean的生命周期,为了了解Bean的生命周期,我们创建一个SpringBoot的启动类,然后写一个close方法,用来销毁Spring容器,用来观察bean的销毁过程。

@SpringBootApplication
public class A03Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(A03Application.class, args);
        context.close();
    }
}

然后我们再创建一个类,在这个类的关键部分我们都打了日志,比如构造方法,依赖注入,初始化方法,和销毁方法。这些日志方便我们后续观察bean的生命周期。

@Component
public class LifeCycleBean {
    private static final Logger log = LoggerFactory.getLogger(LifeCycleBean.class);

    public LifeCycleBean() {
        log.debug("构造");
    }

    @Autowired
    public void autowire(@Value("${JAVA_HOME}") String home) {
        log.debug("依赖注入:{}", home);
    }

    @PostConstruct
    public void init() {
        log.debug("初始化");
    }

    @PreDestroy
    public void destroy() {
        log.debug("销毁");
    }
}

前面的文章中我们讲到bean的后处理器,这里我们观察bean的生命周期还会用到bean的后处理器,分别是InstantiationAwareBeanPostProcessor和DestructionAwareBeanPostProcessor后处理器,前者是在bean实例化前后进行处理的后处理器,后者是销毁前进行处理的后处理器。他们都是BeanPostProcessor后处理器接口的子类。

我们同时实现这两个接口,并复写其中的方法。

@Component
public class MyBeanPostprocessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {

    private static final Logger log = LoggerFactory.getLogger(MyBeanPostprocessor.class);

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("<<< 销毁之前执行,如@PreDestroy");
        }
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("<<< 实例化之前执行,这里返回的对象会替换掉原本的bean");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("<<< 实例化之后执行,这里如果返回false会跳过依赖注入阶段");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("<<< 依赖注入阶段执行,如@Autowired、@Value、@Resource");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("<<< 初始化之前执行,这里返回的对象会替换原本的bean,如@PostConstruct、@ConfigurationProperties");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")){
            log.debug("<<< 初始化之后执行,这里返回的对象会替换掉原本的bean,如代理增强");
        }
        return bean;
    }
}

为了让日志不打印过多的内容方便我们观察,在每个方法中都对beanName进行了判断,只有名字是lifeCycleBean才进行日志输出,方便我们进行观察。

我们启动main方法,观察日志输出

2022-04-19 10:20:43.799 DEBUG 14484 --- [           main] c.z.s.a03.MyBeanPostprocessor            : <<< 实例化之前执行,这里返回的对象会替换掉原本的bean
2022-04-19 10:20:43.800 DEBUG 14484 --- [           main] c.z.springsource.a03.LifeCycleBean       : 构造
2022-04-19 10:20:43.802 DEBUG 14484 --- [           main] c.z.s.a03.MyBeanPostprocessor            : <<< 实例化之后执行,这里如果返回false会跳过依赖注入阶段
2022-04-19 10:20:43.803 DEBUG 14484 --- [           main] c.z.s.a03.MyBeanPostprocessor            : <<< 依赖注入阶段执行,如@Autowired、@Value、@Resource
2022-04-19 10:20:43.804 DEBUG 14484 --- [           main] c.z.springsource.a03.LifeCycleBean       : 依赖注入:C:\Program Files\Java\jdk1.8.0_121
2022-04-19 10:20:43.805 DEBUG 14484 --- [           main] c.z.s.a03.MyBeanPostprocessor            : <<< 初始化之前执行,这里返回的对象会替换原本的bean,如@PostConstruct、@ConfigurationProperties
2022-04-19 10:20:43.805 DEBUG 14484 --- [           main] c.z.springsource.a03.LifeCycleBean       : 初始化
2022-04-19 10:20:43.805 DEBUG 14484 --- [           main] c.z.s.a03.MyBeanPostprocessor            : <<< 初始化之后执行,这里返回的对象会替换掉原本的bean,如代理增强
2022-04-19 10:20:44.078  INFO 14484 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-04-19 10:20:44.090  INFO 14484 --- [           main] c.z.springsource.a03.A03Application      : Started A03Application in 3.731 seconds (JVM running for 7.211)
2022-04-19 10:20:44.913 DEBUG 14484 --- [           main] c.z.s.a03.MyBeanPostprocessor            : <<< 销毁之前执行,如@PreDestroy
2022-04-19 10:20:44.913 DEBUG 14484 --- [           main] c.z.springsource.a03.LifeCycleBean       : 销毁

从日志中我们可以发现,bean的生命周期分为:构造 -> 依赖注入->初始化->销毁

我们可以利用后处理器在bean的各个阶段对bean做一些操作。


4.Spring5底层原理之Bean的生命周期
https://www.zhaojun.inkhttps://www.zhaojun.ink/archives/spring-bean-life-cycle
作者
卑微幻想家
发布于
2022-04-19
许可协议