【Spring高级】第3讲 Bean的生命周期

目录

基本的生命周期

为了演示生命周期的过程,我们直接使用 SpringApplication.run()方法,他会直接诶返回一个容器对象。

java 复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;


@SpringBootApplication
public class BeanLifecycleTest {

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

然后定义一个Bean,如下:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;


@Component
public class LifeCycleBean {

    public LifeCycleBean() {
        System.out.println("构造方法");
    }

    /**
     * 依赖注入方法
     * 当参数是一个对象时,可以直接注入
     * 但是如果是String类型,则需要使用@Value,找到环境变量JAVA_HOME
     *
     * @param home
     */
    @Autowired
    public void autowired(@Value("${JAVA_HOME}") String home) {
        System.out.println("依赖注入");
    }

  	/**
     *  @PostConstruct 用来标记 bean 初始化完成后的回调方法
     */
    @PostConstruct
    public void init() {
        System.out.println("初始化");
    }

  	/**
     * @PreDestroy 用来标记 bean 销毁前的回调方法
     */
    @PreDestroy
    public void destory() {
        System.out.println("销毁");
    }

}

上面的LifeCycleBean我们定义了构造方法、初始化方法、依赖注入方法、销毁方法。

启动应用,打印如下:

构造方法
依赖注入
初始化
2024-02-29 22:53:29.169  INFO 39870 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2024-02-29 22:53:29.182  INFO 39870 --- [           main] c.c.demo02.chapter03.BeanLifecycleTest   : Started BeanLifecycleTest in 1.724 seconds (JVM running for 7.593)
2024-02-29 22:53:29.191  INFO 39870 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
销毁

上面就可以看出整个流程。

后处理器

除了基本的生命周期,下面看下加上后处理器后的流程。

java 复制代码
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;


@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            System.out.println("<<<<< postProcessBeforeDestruction 销毁之前执行");
        }
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            System.out.println("<<<<< postProcessBeforeInstantiation 实例化之前执行");
        }
        return null;
//        return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
    }

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

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        //  依赖注入阶段执行,如@Autowired,@Value @Resource
        if (beanName.equals("lifeCycleBean")) {
            System.out.println("<<<<< postProcessProperties 依赖注入阶段执行");
        }
        return null;
//        return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 初始化之前执行,如@PostConstruct,@ConfigurationProperties
        if (beanName.equals("lifeCycleBean")) {
            System.out.println("<<<<< postProcessBeforeInitialization 初始化之前执行");
        }
        return null;
//        return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 一般这个阶段是替换掉原有的bean,代替增强
        if (beanName.equals("lifeCycleBean")) {
            System.out.println("<<<<< postProcessAfterInitialization 初始化之后执行");
        }
        return null;
//        return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

再次执行,结果如下

shell 复制代码
<<<<< postProcessBeforeInstantiation 实例化之前执行
构造方法
<<<<< postProcessBeforeInstantiation 实例化之后执行
<<<<< postProcessProperties 依赖注入阶段执行
依赖注入
<<<<< postProcessBeforeInitialization 初始化之前执行
<<<<< postProcessAfterInitialization 初始化之后执行
2024-02-29 23:47:57.110  INFO 42057 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2024-02-29 23:47:57.145  INFO 42057 --- [           main] c.c.demo02.chapter03.BeanLifecycleTest   : Started BeanLifecycleTest in 2.242 seconds (JVM running for 8.116)
2024-02-29 23:47:57.158  INFO 42057 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
<<<<< postProcessBeforeDestruction 销毁之前执行
销毁

通过上面可以看出,各个后置处理器分别作用在Bean生命周期的哪个阶段了。

总结

基本生命周期
创建 依赖注入 初始化 可用 销毁

创建前后的增强

  • postProcessBeforeInstantiation:这里返回的对象若不为 null 会替换掉原本的 bean,并且仅会走 postProcessAfterInitialization 流程
  • postProcessAfterInstantiation:这里如果返回 false 会跳过依赖注入阶段

依赖注入前的增强

  • postProcessProperties:如 @Autowired、@Value、@Resource

初始化前后的增强

  • postProcessBeforeInitialization:这里返回的对象会替换掉原本的 bean,如 @PostConstruct、@ConfigurationProperties
  • postProcessAfterInitialization :这里返回的对象会替换掉原本的 bean,如代理增强

销毁之前的增强

  • postProcessBeforeDestruction:如 @PreDestroy
相关推荐
utmhikari5 分钟前
【架构艺术】Go语言微服务monorepo的代码架构设计
后端·微服务·架构·golang·monorepo
蜡笔小新星7 分钟前
Flask项目框架
开发语言·前端·经验分享·后端·python·学习·flask
计算机学姐11 分钟前
基于Asp.net的驾校管理系统
vue.js·后端·mysql·sqlserver·c#·asp.net·.netcore
欢乐少年19042 小时前
SpringBoot集成Sentry日志收集-3 (Spring Boot集成)
spring boot·后端·sentry
夏天的味道٥3 小时前
使用 Java 执行 SQL 语句和存储过程
java·开发语言·sql
冰糖码奇朵5 小时前
大数据表高效导入导出解决方案,mysql数据库LOAD DATA命令和INTO OUTFILE命令详解
java·数据库·sql·mysql
好教员好5 小时前
【Spring】整合【SpringMVC】
java·spring
浪九天6 小时前
Java直通车系列13【Spring MVC】(Spring MVC常用注解)
java·后端·spring
小斌的Debug日记6 小时前
框架基本知识总结 Day16
redis·spring
堕落年代6 小时前
Maven匹配机制和仓库库设置
java·maven