描述一下 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 对象
相关推荐
鬼火儿10 小时前
SpringBoot】Spring Boot 项目的打包配置
java·后端
cr7xin10 小时前
缓存三大问题及解决方案
redis·后端·缓存
yoke菜籽10 小时前
面试150——字典树
面试·职场和发展
间彧11 小时前
Kubernetes的Pod与Docker Compose中的服务在概念上有何异同?
后端
间彧11 小时前
从开发到生产,如何将Docker Compose项目平滑迁移到Kubernetes?
后端
零雲11 小时前
java面试:有了解过RocketMq架构么?详细讲解一下
java·面试·java-rocketmq
间彧11 小时前
如何结合CI/CD流水线自动选择正确的Docker Compose配置?
后端
间彧11 小时前
在多环境(开发、测试、生产)下,如何管理不同的Docker Compose配置?
后端
间彧11 小时前
如何为Docker Compose中的服务配置健康检查,确保服务真正可用?
后端