Spring Bean的生命周期

Spring Bean的生命周期,不仅涵盖每个阶段的细节,还包括Spring内部如何处理这些阶段,以及如何利用这些阶段来满足特定的需求。

1. Spring容器的启动

在Spring容器启动时,它会读取配置元数据(XML配置文件、Java配置类或注解),并开始实例化和初始化Bean。Spring容器的启动通常从调用ApplicationContext的实现类(如ClassPathXmlApplicationContextAnnotationConfigApplicationContext)的构造函数开始。在启动过程中,容器会执行一系列初始化操作,其中包括加载Bean定义、解析依赖关系以及初始化Bean。

2. 实例化 (Instantiation)

当Spring容器需要创建一个Bean时,它首先会根据配置信息调用相应的构造函数来实例化Bean。这个过程是通过BeanFactory来完成的。如果Bean定义中指定了工厂方法,那么Spring会调用该方法来创建Bean。

  • 无参构造器:这是最常见的实例化方式。
  • 工厂方法 :可以通过factory-beanfactory-method属性指定工厂Bean和工厂方法。
  • 静态工厂方法 :如果指定了class属性为静态工厂类,并且factory-method属性为静态方法,那么Spring会调用该静态方法来创建Bean。

3. 属性填充 (Populate Bean Properties)

一旦Bean被实例化,Spring就会开始填充Bean的属性。这个过程包括依赖注入和其他属性设置。

  • 依赖注入 :Spring根据Bean定义中的<property>标签或@Autowired注解来注入依赖。
  • 自动装配 :Spring支持通过autowire属性来自动装配依赖,或者使用@Autowired注解来实现自动装配。

4. 设置Bean名称 (Bean Name Aware)

如果Bean实现了BeanNameAware接口,Spring会在Bean的属性设置之后,但在初始化之前调用setBeanName方法,将Bean的名称传递给Bean。

public class MyBean implements BeanNameAware {
    private String beanName;

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("BeanNameAware: Bean name is " + name);
    }
}

5. 设置Bean工厂 (Bean Factory Aware)

如果Bean实现了BeanFactoryAware接口,Spring会在属性设置之后,但在初始化之前调用setBeanFactory方法,将BeanFactory传递给Bean。

public class MyBean implements BeanFactoryAware {
    private BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory factory) throws BeansException {
        this.beanFactory = factory;
        System.out.println("BeanFactoryAware: BeanFactory is set");
    }
}

6. 设置应用上下文 (Application Context Aware)

如果Bean实现了ApplicationContextAware接口,Spring会在属性设置之后,但在初始化之前调用setApplicationContext方法,将ApplicationContext传递给Bean。

public class MyBean implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        this.applicationContext = context;
        System.out.println("ApplicationContextAware: ApplicationContext is set");
    }
}

7. 预初始化处理 (Pre-Initialization Processing)

在Bean初始化之前,Spring会调用所有注册的BeanPostProcessorpostProcessBeforeInitialization方法。BeanPostProcessor接口允许我们在Bean初始化前后插入自定义逻辑。

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor: Before initialization of " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor: After initialization of " + beanName);
        return bean;
    }
}

8. 初始化 (Initialization)

  • InitializingBean接口 :如果Bean实现了InitializingBean接口,Spring会在属性设置之后调用afterPropertiesSet方法。

    public class MyBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
    System.out.println("InitializingBean: afterPropertiesSet method called");
    }
    }

  • init-method :如果在Bean定义中指定了init-method属性,Spring会调用该方法。

    <bean id="myBean" class="com.example.MyBean" init-method="customInit"/>
  • @PostConstruct注解 :如果Bean的方法上标注了@PostConstruct,Spring会在依赖注入完成后调用该方法。

    public class MyBean {
    @PostConstruct
    public void init() {
    System.out.println("@PostConstruct: Initialization method called");
    }
    }

9. 后初始化处理 (Post-Initialization Processing)

在Bean初始化之后,Spring会再次调用所有注册的BeanPostProcessorpostProcessAfterInitialization方法。

10. 使用 (Usage)

此时,Bean已经完全初始化,可以被应用程序使用。Spring容器会将Bean存储在单例池中(如果是单例作用域),以便后续请求时可以直接获取。

11. 销毁 (Destruction)

  • DisposableBean接口 :如果Bean实现了DisposableBean接口,Spring会在容器关闭时调用destroy方法。

    public class MyBean implements DisposableBean {
    @Override
    public void destroy() throws Exception {
    System.out.println("DisposableBean: destroy method called");
    }
    }

  • destroy-method :如果在Bean定义中指定了destroy-method属性,Spring会在容器关闭时调用该方法。

    <bean id="myBean" class="com.example.MyBean" destroy-method="customDestroy"/>
  • @PreDestroy注解 :如果Bean的方法上标注了@PreDestroy,Spring会在销毁Bean之前调用该方法。

    public class MyBean {
    @PreDestroy
    public void cleanup() {
    System.out.println("@PreDestroy: Cleanup method called");
    }
    }

示例代码

下面是一个完整的示例,展示了如何在一个Bean中实现和使用这些接口和注解。

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
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.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Component
@Lazy
public class MyBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {

    private String beanName;
    private BeanFactory beanFactory;
    private ApplicationContext applicationContext;

    // 构造函数
    public MyBean() {
        System.out.println("MyBean instance created.");
    }

    // BeanNameAware接口方法
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("BeanNameAware: Bean name is " + name);
    }

    // BeanFactoryAware接口方法
    @Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
        System.out.println("BeanFactoryAware: BeanFactory is set");
    }

    // ApplicationContextAware接口方法
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("ApplicationContextAware: ApplicationContext is set");
    }

    // InitializingBean接口方法
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean: afterPropertiesSet method called");
    }

    // @PostConstruct注解的方法
    @PostConstruct
    public void init() {
        System.out.println("@PostConstruct: Initialization method called");
    }

    // @PreDestroy注解的方法
    @PreDestroy
    public void cleanup() {
        System.out.println("@PreDestroy: Cleanup method called");
    }

    // DisposableBean接口方法
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean: destroy method called");
    }
}

总结

Spring Bean的生命周期是一个高度灵活和可扩展的过程。通过实现不同的生命周期回调接口和使用注解,我们可以控制Bean在各个阶段的行为。这使得我们能够有效地管理Bean的初始化和清理,尤其是在处理外部资源(如数据库连接、网络连接等)时尤为重要。

此外,Spring还提供了许多其他的扩展点,如BeanPostProcessorBeanFactoryPostProcessor等,这些都可以用来在Bean的生命周期中插入自定义逻辑。

相关推荐
2401_8576100312 分钟前
Spring Boot框架:电商系统的技术优势
java·spring boot·后端
LuckyLay27 分钟前
Spring学习笔记_34——@Controller
spring·controller
希忘auto29 分钟前
详解MySQL安装
java·mysql
冰淇淋烤布蕾40 分钟前
EasyExcel使用
java·开发语言·excel
拾荒的小海螺1 小时前
JAVA:探索 EasyExcel 的技术指南
java·开发语言
Jakarta EE1 小时前
正确使用primefaces的process和update
java·primefaces·jakarta ee
马剑威(威哥爱编程)1 小时前
哇喔!20种单例模式的实现与变异总结
java·开发语言·单例模式
java—大象1 小时前
基于java+springboot+layui的流浪动物交流信息平台设计实现
java·开发语言·spring boot·layui·课程设计
ApiHug2 小时前
ApiSmart x Qwen2.5-Coder 开源旗舰编程模型媲美 GPT-4o, ApiSmart 实测!
人工智能·spring boot·spring·ai编程·apihug
杨哥带你写代码2 小时前
网上商城系统:Spring Boot框架的实现
java·spring boot·后端