• SpringBoot中bean的生命周期


    概述

    Bean 生命周期管理是 Spring Boot 中的关键功能之一。它负责管理应用程序中的 Java 对象,这些对象被称为 Beans。Spring Boot 通过创建、配置、初始化和销毁这些 Beans 来确保应用程序的正常运行。这个功能的目的是提供一种灵活的方式,使开发人员能够轻松地管理对象的生命周期,从而实现高效的依赖注入和组件化开发。

    1、实例化:在 Spring 容器启动时,Spring 会创建配置中定义的所有 Bean。这是通过 Java 类的构造函数或工厂方法来完成的。

    2、属性注入:一旦 Bean 被实例化,Spring 会注入所有相关的属性,包括通过构造函数注入或 Setter 方法注入的属性。

    3、初始化方法调用:一旦属性被注入,Spring 容器会调用 Bean 的初始化方法。这可以通过@PostConstruct注解、实现InitializingBean接口来完成。初始化过程还提供了一些扩展口:BeanNameAware,BeanFactoryAware,ApplicationContextAware

    4、使用 Bean:Bean 现在可以在应用程序中使用,执行其业务逻辑。

    5、销毁方法调用:当 Spring 容器关闭时,它会调用 Bean 的销毁方法以释放资源。这可以通过@PreDestroy注解、实现DisposableBean接口来完成。

    使用场景

    • 依赖注入:当你需要将一个对象注入到另一个对象中时,Bean 的生命周期管理可以确保被注入的对象已正确初始化。
    • 配置管理:如果你希望根据不同的环境或配置文件来配置 Bean 的属性,Bean 的生命周期管理可以帮助你实现这一目标。
    • 组件扩展:当你需要创建自定义的 Bean,以扩展 Spring Boot 的功能时,Bean 的生命周期管理可以为你提供扩展点。
    • 切面编程:可以在生命周期中预埋代码实现切面编程。例如SpringBoot AOP代理类的实现。

    代码演示bean初始化

    编写代码演示bean初始化各个节点。

    演示代码将创建以下类:

    • TestSupport:一个普通的组件,将作为被观测对象
    • BeanPostProcessorImpl:BeanPostProcessor接口的实现类,用于实现postProcessBeforeInitialization 和postProcessAfterInitialization 并观测TestSupport对象

    TestSupport

    
    
    import com.alibaba.fastjson2.JSON;
    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.BeanNameAware;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    import javax.annotation.PostConstruct;
    
    @Slf4j
    @RequiredArgsConstructor
    @Component
    public class TestSupport implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean {
    
        private final ApplicationContext  applicationContext;
        
        @Override
        public void setBeanName(String s) {
            log.info("TestSupport-BeanNameAware-setBeanName.param={}", s);
        }
        
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            log.info("TestSupport-BeanFactoryAware-setBeanFactory.param={}", "beanFactory");
        }
        
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            log.info("TestSupport-ApplicationContextAware-setApplicationContext.param={}", JSON.toJSONString(applicationContext.getId()));
        }
        
        @Override
        public void afterPropertiesSet() throws Exception {
            log.info("TestSupport-InitializingBean-afterPropertiesSet");
        }
        
        @PostConstruct
        public void InitSomething() {
            log.info("通过 @PostConstruct 注解执行自定义初始化逻辑");
        }
    }
    
    
    
    
    • BeanNameAware:通过实现BeanNameAware接口并重写setBeanName方法可以获取到bean的name
    • BeanFactoryAware:通过实现BeanFactoryAware接口并重写setBeanFactory方法可以在bean初始化过程中添加额外的扩展,比如可以通过判断beanFactory.alreadyCreated中是否有某bean而做一些不同的操作
    • ApplicationContextAware:通过实现ApplicationContextAware接口并重写setApplicationContext方法可以在bean初始化过程中添加额外扩展。
    • InitializingBean:通过实现InitializingBean接口并重写afterPropertiesSet 方法可以在bean初始化过程中添加额外扩展。比如将此bean存入map中以备它用
    • @PostConstruct:此外还可以通过在方法上面添加@PostConstruct注解来执行一些自定义的业务代码

    BeanPostProcessorImpl

    
    
    import com.ramble.beanlife.support.TestSupport;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.stereotype.Component;
    @Slf4j
    @Component
    public class BeanPostProcessorImpl implements BeanPostProcessor {
        /**
         * bean 加工器之在bean实例化之前得预处理
         * 这个处理类针对所有得bean,所以如果需要对特定得bean做处理需要通过 beanName.equals("testSupport")  或者  bean instanceof TestSupport 来过滤
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    //        if (beanName.equals("testSupport")) {
    //            log.info("执行  TestSupport 初始化前置方法");
    //        }
            if (bean instanceof TestSupport) {
                log.info("bean 加工器捕捉到  TestSupport ,做初始化前置方法");
            }
            // do something
            return bean;
        }
        /**
         * bean 加工器之在bean实例化之后得预处理
         * @param bean
         * @param beanName
         * @return
         * @throws BeansException
         */
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    //        if (beanName.equals("testSupport")) {
    //            log.info("执行 TestSupport 初始化后置方法");
    //        }
            if (bean instanceof TestSupport) {
                log.info("bean 加工器捕捉到  TestSupport ,做初始化后置方法");
            }
            // do something
            return bean;
        }
    }
    
    
    
    
    
    • postProcessBeforeInitialization:bean 加工器之在bean初始化完毕之前的预处理
    • postProcessAfterInitialization:bean 加工器之在bean初始化之后的预处理
    • 这个扩展点是针对所有的bean的,所以如果需要观测特定的bean在BeanPostProcessor中的情况,需要通过 bean instanceof 或者 beanName equals 进行判断

    log

    
    2024-04-07 15:25:33.488  INFO 51628 --- [           main] com.ramble.beanlife.support.TestSupport  : TestSupport-BeanNameAware-setBeanName.param=testSupport
    2024-04-07 15:25:35.271  INFO 51628 --- [           main] com.ramble.beanlife.support.TestSupport  : TestSupport-BeanFactoryAware-setBeanFactory.param=beanFactory
    2024-04-07 15:25:35.783  INFO 51628 --- [           main] com.ramble.beanlife.support.TestSupport  : TestSupport-ApplicationContextAware-setApplicationContext.param="bean-life-app"
    2024-04-07 15:25:36.198  INFO 51628 --- [           main] c.r.b.processor.BeanPostProcessorImpl    : bean 加工器捕捉到  TestSupport ,做初始化前置方法
    2024-04-07 15:25:36.651  INFO 51628 --- [           main] com.ramble.beanlife.support.TestSupport  : 通过 @PostConstruct 注解执行自定义初始化逻辑
    2024-04-07 15:25:36.652  INFO 51628 --- [           main] com.ramble.beanlife.support.TestSupport  : TestSupport-InitializingBean-afterPropertiesSet
    2024-04-07 15:25:38.453  INFO 51628 --- [           main] c.r.b.processor.BeanPostProcessorImpl    : bean 加工器捕捉到  TestSupport ,做初始化后置方法
    
    

    通过log打印的顺序可以观测到bean初始化的各个扩展口的执行顺序。

    代码

    https://gitee.com/naylor_personal/ramble-spring-boot/tree/master/bean-life


    __EOF__

  • 本文作者: 一颗苹果
  • 本文链接: https://www.cnblogs.com/naylor/p/18119168
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    安卓游戏开发之音频技术优劣分析
    【SpringCloud】OpenFeign服务接口调用快速入门
    为什么会突然牙疼?
    正弦信号的平均功率和峰值电压计算举例
    【网络协议】 TCP与UDP协议区别及应用场景深度分析
    XML语言的学习记录2-XMLHttpRequest
    离散信号的卷积与相关
    基于JAVA工厂生产计划与进度管理系统计算机毕业设计源码+数据库+lw文档+系统+部署
    矩阵分析学习笔记(六):有理标准型和Jordan标准型、复数域上矩阵的特征结构
    C++ 构造函数
  • 原文地址:https://www.cnblogs.com/Naylor/p/18119168