例子演示Spring bean生命周期方法的调用顺序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/84794772

项目简介

  • 基于 springboot 2.1.1
  • 使用 maven 管理项目
  • web 项目

源代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>tut</groupId>
    <artifactId>zero</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
</project>

配置文件 application.yml

threshold: 1000

主程序类

package tut.zero;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    MyBean bean;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) {
        bean.serve();
    }
}

用于观察bean生命周期方法调用顺序而自定义的bean

package tut.zero;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

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

/**
 * 一个为了演示bean生命周期方法调用顺序而专门设计的bean,没有任何实际的业务意义
 */
@Component // 该注解让该类作为一个bean定义被容器发现
public class MyBean implements InitializingBean, DisposableBean, BeanNameAware, BeanClassLoaderAware,
        BeanFactoryAware, ApplicationContextAware {
    /**
     * 构造函数,响应 Java new 操作符
     */
    public MyBean() {
        System.out.println("1.bean构造阶段 - 1.新建对象 - 构造函数被调用");
    }

    /**
     * 和方法 setThreshold() 配合演示一个配置属性的注入,初始值设置为 null
     * 如果使用时为 null,表明带注解 @Value 的方法 setThreshold() 未被调用
     */
    Integer threshold = null;

    @Value("${threshold}")
    public void setThreshold(int threshold) {
        System.out.println("1.bean构造阶段 - 2.填充属性 - bean属性注入方法被调用 - @Value setThreshold()");
        this.threshold = threshold;
    }


    /**
     * @param environment
     */
    @Autowired
    public void setEnvironment(Environment environment) {
        System.out.println("1.bean构造阶段 - 2.填充属性 - bean依赖注入方法被调用 - @Autowired setEnvironment()");
        this.environment = environment;
    }

    /**
     * 和方法 setEnvironment() 配合演示一个 bean 的注入,初始值设置为 null
     * 如果使用时为 null,表明带注解 @Autowired 的方法 setEnvironment() 未被调用
     */
    Environment environment;

    /**
     * JSR-250 定义的初始化机会
     */
    @PostConstruct
    public void postConstruct() {
        // 这里观察依赖注入和属性设置是否已经完成
        final boolean dependentBeanResolved = this.environment != null;
        final boolean dependentPropertyResolved = this.threshold != null;
        System.out.printf(
                "1.bean构造阶段 - 3.初始化 - JSR-250 @PostConstruct - " +
                        "@Autowired注解bean已设置 : %s ,@Value注入属性已设置 : %s \n",
                dependentBeanResolved,
                dependentPropertyResolved
        );
    }


    /**
     * InitializingBean接口定义的初始化机会
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("1.bean构造阶段 - 3.初始化 " +
                "- InitializingBean#afterPropertiesSet");
    }


    /**
     * 模拟一个该bean组件提供的业务方法,
     * 1. 这些业务方法可以有多个
     * 2. 每个这样的方法由开发人员根据业务逻辑定义决定如何调用
     * 3. 这些方法的调用应该发生在bean被创建和初始化过程结束之后,销毁阶段开始之前
     * 4. 对于一般的单例bean,首次注入过程视为该bean创建和初始化过程,将程序结束时容器销毁的过程看作bean进入销毁阶段,
     * 换句话讲,当你通过依赖注入方式拿到一个bean实例之后,这个bean实例的创建和初始化过程已经由容器完成,可以用于
     * 调用这些业务方法了。bean的销毁也是在程序进入结束流程时由容器完成的,开发人员有机会在bean销毁时做一些事情,
     * 但一般来说业务开发人员并不需要太关注bean的销毁流程。
     */
    public void serve() {
        System.out.println("2.bean服务阶段 - 业务方法被调用");
    }

    /**
     * JSR-250 定义的析构机会
     */
    @PreDestroy
    public void preDestroy() {
        System.out.println("3.bean销毁阶段 - 1.JSR-250 @PreDestroy");
    }

    /**
     * DisposableBean 接口定义的析构机会
     *
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("3.bean销毁阶段 - 2.DisposableBean#destroy");
    }


    /**
     * BeanNameAware 接口要求的方法
     *
     * @param name
     */
    public void setBeanName(String name) {
        System.out.printf("1.bean构造阶段 - 3.初始化 - " +
                "Aware 接口方法调用 - BeanNameAware#setBeanName\n");
    }

    /**
     * BeanClassLoaderAware 接口要求的方法
     *
     * @param classLoader
     */
    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.printf("1.bean构造阶段 - 3.初始化 - " +
                "Aware 接口方法调用 - BeanClassLoaderAware#setBeanClassLoader\n");
    }

    /**
     * BeanFactoryAware 接口要求的方法
     *
     * @param beanFactory
     * @throws BeansException
     */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.printf("1.bean构造阶段 - 3.初始化 - " +
                "Aware 接口方法调用 - BeanFactoryAware#setBeanFactory\n");
    }

    /**
     * ApplicationContextAware 接口要求的方法
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.printf("1.bean构造阶段 - 3.初始化 - " +
                "Aware 接口方法调用 - ApplicationContextAware#setApplicationContext\n");
    }
}

用于观察bean生命周期方法调用顺序而自定义的BeanPostProcessor

package tut.zero;

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

/**
 * 针对bean定义 MyBean 设计的一个 BeanPostProcessor 实现,没有任何业务意义,
 * 只是用来配合演示 bean 生命周期方法调用的顺序
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyBean)
            System.out.printf("1.bean构造阶段 - 3.初始化 - " +
                    "MyBeanPostProcessor#postProcessBeforeInitialization('%s')\n", beanName);
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyBean)
            System.out.printf("1.bean构造阶段 - 3.初始化 - " +
                    "MyBeanPostProcessor#postProcessAfterInitialization('%s')\n", beanName);
        return bean;
    }
}

bean生命周期方法调用顺序

1.bean构造阶段 - 1.新建对象 - 构造函数被调用
1.bean构造阶段 - 2.填充属性 - bean属性注入方法被调用 - @Value setThreshold()
1.bean构造阶段 - 2.填充属性 - bean依赖注入方法被调用 - @Autowired setEnvironment()
1.bean构造阶段 - 3.初始化 - Aware 接口方法调用 - BeanNameAware#setBeanName
1.bean构造阶段 - 3.初始化 - Aware 接口方法调用 - BeanClassLoaderAware#setBeanClassLoader
1.bean构造阶段 - 3.初始化 - Aware 接口方法调用 - BeanFactoryAware#setBeanFactory
1.bean构造阶段 - 3.初始化 - Aware 接口方法调用 - ApplicationContextAware#setApplicationContext
1.bean构造阶段 - 3.初始化 - MyBeanPostProcessor#postProcessBeforeInitialization('myBean')
1.bean构造阶段 - 3.初始化 - JSR-250 @PostConstruct - @Autowired注解bean已设置 : true ,@Value注入属性已设置 : true 
1.bean构造阶段 - 3.初始化 - InitializingBean#afterPropertiesSet
1.bean构造阶段 - 3.初始化 - MyBeanPostProcessor#postProcessAfterInitialization('myBean')
2.bean服务阶段 - 业务方法被调用
3.bean销毁阶段 - 1.JSR-250 @PreDestroy
3.bean销毁阶段 - 2.DisposableBean#destroy

相关文章

Spring bean的生命周期

猜你喜欢

转载自blog.csdn.net/andy_zhang2007/article/details/84794772