Spring bean的生命周期

一、Spring框架中Bean的生命周期

可以分为以下几个主要阶段:

1. 实例化: 当Spring容器启动并读取配置元数据(如XML配置、注解或Java配置类)时,它会创建Bean定义的实例。对于 singleton scope 的Bean,这会在容器启动时发生一次;而对于 prototype scope,每次请求Bean时都会创建新实例。

2. 属性填充: Spring通过反射调用Bean实例的setter方法或使用构造器注入来设置依赖项。这包括注入其他Bean、基本类型的值或集合类型的属性。

3. Aware接口注入: 如果Bean实现了Spring的Aware接口(如BeanNameAware、ApplicationContextAware等),Spring会调用相应的回调方法,允许Bean知道它们所在的容器或它们的Bean名称等信息。

4. 初始化前处理: 如果Bean定义中指定了InitializingBean接口,Spring会调用其afterPropertiesSet()方法。这是在自定义初始化回调之前执行的,可以用来执行一些初始化工作。

5. 自定义初始化方法: 开发者可以通过@PostConstruct注解或在Spring配置中指定init-method属性来定义自定义的初始化方法。Spring会在所有必需的属性设置之后调用这些方法。

6. Bean准备就绪: 至此,Bean已经完全初始化并准备好被应用程序使用。对于 singleton Beans,它们将被放入Spring容器的单例缓存中。

7. 使用Bean: 应用程序可以通过依赖查找或自动装配来使用Bean。

8. 销毁前处理: 如果Bean实现了DisposableBean接口,当容器关闭时,Spring会调用其destroy()方法。此外,也可以使用@PreDestroy注解或在配置中指定destroy-method来执行自定义的销毁逻辑。

9. 销毁: 对于非 singleton scope 的Bean(如 prototype),Spring容器不负责销毁,而是由Java垃圾收集器来处理。对于 singleton scope 的Bean,当Spring容器关闭时,会执行销毁方法,释放资源。

二、Spring Bean生命周期的案例,使用Java配置方式来展示各个阶段

 1. 定义一个简单的Bean类,包含初始化和销毁方法:


import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class ExampleBean {

  public ExampleBean() {
    System.out.println("2. Bean实例化 - 调用构造函数");
  }

  // 使用@PostConstruct注解标记初始化方法
  @PostConstruct
  public void init() {
    System.out.println("3. 初始化 - 调用@PostConstruct注解的方法");
  }

  // 使用@PreDestroy注解标记销毁方法
  @PreDestroy
  public void cleanup() {
    System.out.println("9. 销毁 - 调用@PreDestroy注解的方法");
  }

  public void sayHello() {
    System.out.println("bean内部方法:Hello from ExampleBean!");
  }

  // 自定义初始化方法,现在看来@PostConstruct注解已经可以满足需求了,但是还是留着自定义初始化方法的例子
  private void customInit() {
    System.out.println("customInit - 调用customInit");
  }
}

2. 创建Spring的Java配置类,配置ExampleBean


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

  // 定义Bean
  @Bean(initMethod = "customInit", destroyMethod = "cleanup")
  public ExampleBean exampleBean() {
    System.out.println("1. Bean实例化 - Spring调用配置方法创建Bean");
    return new ExampleBean();
  }
}

尽管我们已经在ExampleBean中使用了@PostConstruct和@PreDestroy注解,这里为了演示配置方式,仍然在@Bean注解中指定了初始化和销毁方法。实际上,直接使用注解通常是首选。

3. 编写一个主类来启动Spring容器并使用Bean:

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MainApp {

    public static void main(String[] args) {
        System.out.println("0. Spring容器初始化开始");

        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        System.out.println("4. Bean已准备就绪,可以使用");

        ExampleBean bean = context.getBean(ExampleBean.class);
        bean.sayHello();

        System.out.println("8. Spring容器关闭开始");

        ((AnnotationConfigApplicationContext) context).close();

        System.out.println("10. Spring容器已关闭");
    }
}

当运行MainApp时,控制台输出将按照以下顺序显示:

0. Spring容器初始化开始

1. Bean实例化 - Spring调用配置方法创建Bean
2. Bean实例化 - 调用构造函数
3. 初始化 - 调用@PostConstruct注解的方法
customInit - 调用customInit
4. Bean已准备就绪,可以使用
bean内部方法:Hello from ExampleBean!
8. Spring容器关闭开始
9. 销毁 - 调用@PreDestroy注解的方法
10. Spring容器已关闭

注:@PostConstruct和initMethod

@PostConstruct
来源: @PostConstruct是JSR-250规范的一部分,它是Java EE提供的标准注解,用于在依赖关系设置之后但在Bean被任何其他Bean使用之前调用初始化方法。
使用场景: 当你需要一个跨框架的标准化初始化注解时,或者你的应用不仅仅局限于Spring框架,那么使用@PostConstruct更为合适。
优点: 标准化,不绑定到特定框架,提高了代码的可移植性。

init-method
来源: init-method是Spring框架特有的配置方式,通过在Spring的XML配置文件或Java配置类中的@Bean注解里指定初始化方法名称。
使用场景: 如果你的应用完全基于Spring框架,并且希望利用Spring提供的更多特性或与Spring的其他配置风格保持一致,那么使用init-method可能更合适。 

@PostConstruct 和 initMethod都可以用来指定Bean的初始化方法,通过上面的案例可知, @PostConstruct 注解更加标准化,最先进行初始化。而 initMethod 更像是一个初始化后,自定义的方法,两者往往可以互换使用,也可以共存使用,但@PostConstruct 标准化更加规范。

相关推荐

  1. springbean生命周期

    2024-06-11 20:48:03       19 阅读
  2. Vue生命周期

    2024-06-11 20:48:03       44 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-11 20:48:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-11 20:48:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-11 20:48:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-11 20:48:03       20 阅读

热门阅读

  1. 03-04-Spring声明式事务

    2024-06-11 20:48:03       12 阅读
  2. 闭包在Python中的魔法

    2024-06-11 20:48:03       12 阅读
  3. Nginx学习笔记

    2024-06-11 20:48:03       10 阅读
  4. 2024.05.28 校招 实习 内推 面经

    2024-06-11 20:48:03       10 阅读
  5. 【Vue】获取模块内的mutations方法

    2024-06-11 20:48:03       10 阅读
  6. Python与MySQL连接和使用

    2024-06-11 20:48:03       8 阅读