描述一下 Spring Bean 的生命周期 ?

Spring Bean 的生命周期是指 Bean 从创建、初始化、使用到销毁的完整过程,核心由 Spring 容器全程管理,主要可分为 4 个核心阶段,关键节点需结合初始化/销毁方法和后置处理器。

spring Bean流程图:

1. Bean 的创建阶段

css 复制代码
容器通过 XML 配置、注解(@Component 等)或 Java 配置类 扫描并定位 Bean 的定义信息(BeanDefinition)。

根据 Bean 的作用域(默认单例),容器在启动时(单例 Bean)或首次获取时(原型 Bean),通过反射调用 Bean 的 无参构造方法 创建实例对象。

2. Bean 的初始化阶段(核心)

初始化是 Bean 功能完善的关键步骤,按顺序执行以下操作:

typescript 复制代码
1.设置属性(依赖注入):容器将 Bean 依赖的其他对象(如 @Autowired 标注的属性)注入到当前 Bean 中。

2.调用Aware接口方法:若 Bean 实现了 BeanNameAware、BeanFactoryAware 等接口,容器会主动调用接口方法,传递 Bean 名称、BeanFactory 等容器信息(如 setBeanName(String name))。

3.调用BeanPostProcessor前置方法:容器中的 BeanPostProcessor 接口实现类,会调用 postProcessBeforeInitialization(Object bean, String beanName),对 Bean 进行初始化前的自定义处理(如AOP代理前置准备)。

4.执行自定义初始化方法:

若通过 XML 配置(init-method 属性)、注解(@PostConstruct)或实现 InitializingBean 接口(afterPropertiesSet() 方法)定义了初始化逻辑,容器会依次执行这些方法。

5.调用BeanPostProcessor后置方法:BeanPostProcessor 实现类调用 postProcessAfterInitialization(Object bean, String beanName),完成初始化后的最终处理(如生成AOP代理对象)。

至此,Bean 已完全初始化,可被容器或业务代码获取并使用。

3. Bean 的使用阶段

初始化完成的 Bean 存储在容器中,根据作用域提供服务:

scss 复制代码
单例 Bean:全程只有一个实例,容器启动后持续存在,供多次获取和使用。

原型 Bean:每次调用 getBean() 都会创建新实例,使用后由 JVM 垃圾回收(Spring 不管理原型 Bean 的销毁)。

4. Bean 的销毁阶段(仅单例 Bean)

当 Spring 容器关闭(如应用停止)时,单例 Bean 会触发销毁流程:

scss 复制代码
1.若 Bean 实现 DisposableBean 接口,容器调用其 destroy() 方法。

2.执行自定义销毁方法:通过 XML 配置(destroy-method 属性)或注解(@PreDestroy)定义的销毁逻辑(如释放数据库连接、关闭线程池)。

3.销毁完成后,Bean 实例被 JVM 垃圾回收。

代码实例:

Book

csharp 复制代码
public class Book implements InitializingBean, DisposableBean, BeanNameAware, BeanFactoryAware, ApplicationContextAware {
    private String title;

    //空参
    public Book() {
        System.out.println("1.实例化 Book 对象");
    }

    //set
    public void setTitle(String title) {
        this.title = title;
        System.out.println("2.依赖注入(属性填充) 设置 Book 对象的 title 属性,title = " + title);
    }

    //get
    public String getTitle() {
        return title;
    }

    //初始化方法
    public void myInit() {
//        System.out.println("3.初始化方法 Book 对象");
        if (title == null) {
            title = "默认书籍"; // 如果没有设置标题,则使用默认标题
            System.out.println("3 初始化方法 Book 对象> 默认标题是:" + title);
        } else {
            System.out.println("3 初始化方法 Book 对象> 标题是:" + title);
        }
    }

    //销毁方法
    public void myDestroy() {
        System.out.println("5.销毁方法 Book 对象");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("2.9.初始化方法 Book 对象 -- afterPropertiesSet");
        if (title == null) {
            title = "默认书籍"; // 如果没有设置标题,则使用默认标题
//            System.out.println("4.1 初始化方法 Book 对象> 默认标题是:" + title);
        } else {
//            System.out.println("4.1 初始化方法 Book 对象> 标题是:" + title);
        }

    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("2.2 设置 Bean 工厂为:" + beanFactory.getClass().getName());

    }

    public void setBeanName(String s) {
        System.out.println("2.1 设置 Bean 名称为:" + s);

    }

    public void destroy() throws Exception {
        System.out.println("4.9 销毁方法 Book 对象 -- DisposableBean");
        // 在这里可以执行一些清理操作,例如关闭资源等

    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("2.3 设置 ApplicationContext 为:" + applicationContext.getClass().getName());

    }
}

BookProcessor

typescript 复制代码
public class BookProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        // 在初始化之前执行
        if (bean instanceof Book) {
            System.out.println("2.5 -- Before Initialization: " + beanName);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 在初始化之后执行
        if (bean instanceof Book) {
            System.out.println("3.5 -- After Initialization: " + beanName);
        }
        return bean;
    }
}

spring.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    定义一个book bean-->
    <bean id="book" class="com.example.demo.bean.Book" init-method="myInit" destroy-method="myDestroy">
        <property name="title" value="Java编程思想"/>
    </bean>

    <!-- 定义一个BookProcessor bean -->
    <bean id="bookProcessor" class="com.example.demo.bean.BookProcessor"/>

</beans>

测试类

csharp 复制代码
 @Test
    public void test4() {
        // 测试类
        //通过注解的方式生成bean的测试
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        // 获取 book 对象
        Book book = context.getBean(Book.class);
        // 4.使用bean
//        System.out.println("8.使用Bean  Cat 对象,name = " + cat.getName());
        System.out.println("4.使用Bean  Book 对象,name = " + book.getTitle());
        // 关闭容器
        ((ClassPathXmlApplicationContext) context).close();
        // 5.销毁 Cat 对象
        // 注意:在使用 ClassPathXmlApplicationContext 时,销毁方法会在 close() 方法调用时自动执行
    }

运行结果如下:

ini 复制代码
1.实例化 Book 对象
2.依赖注入(属性填充) 设置 Book 对象的 title 属性,title = Java编程思想
2.1 设置 Bean 名称为:book
2.2 设置 Bean 工厂为:org.springframework.beans.factory.support.DefaultListableBeanFactory
2.3 设置 ApplicationContext 为:org.springframework.context.support.ClassPathXmlApplicationContext
2.5 -- Before Initialization: book
2.9.初始化方法 Book 对象 -- afterPropertiesSet
3 初始化方法 Book 对象> 标题是:Java编程思想
3.5 -- After Initialization: book
4.使用Bean  Book 对象,name = Java编程思想
4.9 销毁方法 Book 对象 -- DisposableBean
5.销毁方法 Book 对象
相关推荐
行百里er2 小时前
WebSocket 在 Spring Boot 中的实战解析:实时通信的技术利器
spring boot·后端·websocket
NAGNIP3 小时前
一文搞懂树模型与集成模型
算法·面试
NAGNIP3 小时前
万字长文!一文搞懂监督学习中的分类模型!
算法·面试
技术狂人1683 小时前
工业大模型工程化部署实战!4 卡 L40S 高可用集群(动态资源调度 + 监控告警 + 国产化适配)
人工智能·算法·面试·职场和发展·vllm
柳杉4 小时前
建议收藏 | 2026年AI工具封神榜:从Sora到混元3D,生产力彻底爆发
前端·人工智能·后端
仙俊红4 小时前
spring的IoC(控制反转)面试题
java·后端·spring
小楼v4 小时前
说说常见的限流算法及如何使用Redisson实现多机限流
java·后端·redisson·限流算法
与遨游于天地4 小时前
NIO的三个组件解决三个问题
java·后端·nio
czlczl200209255 小时前
Guava Cache 原理与实战
java·后端·spring
Yuer20256 小时前
什么是 Rust 语境下的“量化算子”——一个工程对象的最小定义
开发语言·后端·rust·edca os·可控ai