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

项目简介

  • 基于 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的生命周期

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值