原文: https://howtodoinjava.com/spring-core/spring-bean-life-cycle/

在本文中,了解SpringBean 生命周期。 我们将学习生命周期阶段,初始化和销毁回调方法。 我们将学习使用 XML 配置以及注解配置来控制 bean 生命周期事件。

1. Bean 的生命周期

当容器启动时 – 需要基于 Java 或 XML bean 定义实例化 Spring bean。 可能还需要执行一些初始化后的步骤,以使其进入可用状态。 相同的 bean 生命周期也适用于 SpringBoot 应用程序。

之后,当不再需要该 bean 时,它将被从 IoC 容器中删除。

Spring bean 工厂负责管理通过 spring 容器创建的 bean 的生命周期。

1.1. 生命周期回调

Spring bean 工厂控制 bean 的创建和销毁。 为了执行一些自定义代码,它提供了回调方法,这些方法可以大致分为两类:

  • 初始化后回调方法
  • 销毁回调方法

1.1. 生命周期图示

Spring – Bean 生命周期 - 图1

Spring Bean Life Cycle

2. 生命周期回调方法

Spring 框架提供了以下 4 种方式来控制 Bean 的生命周期事件

  1. InitializingBeanDisposableBean回调接口
  2. *了解特定行为的界面
  3. bean 配置文件中的自定义init()destroy()方法
  4. @PostConstruct@PreDestroy注解

2.1. InitializingBeanDisposableBean

org.springframework.beans.factory.InitializingBean 接口允许 Bean 在容器上设置了所有必需的属性后执行初始化工作。

InitializingBean接口指定一种方法:

InitializingBean.java

  1. void afterPropertiesSet() throws Exception;

这不是初始化 bean 的首选方法,因为它将 bean 类与 spring 容器紧密耦合。 更好的方法是在applicationContext.xml文件中的 bean 定义中使用“初始化方法”属性。

类似地,实现org.springframework.beans.factory.DisposableBean接口允许 Bean 在包含它的容器被销毁时获得回调。

DisposableBean接口指定一种方法:

DisposableBean.java

  1. void destroy() throws Exception;
  2. A sample bean implementing above interfaces would look like this:
  3. package com.howtodoinjava.task;
  4. import org.springframework.beans.factory.DisposableBean;
  5. import org.springframework.beans.factory.InitializingBean;
  6. public class DemoBean implements InitializingBean, DisposableBean
  7. {
  8. //Other bean attributes and methods
  9. @Override
  10. public void afterPropertiesSet() throws Exception
  11. {
  12. //Bean initialization code
  13. }
  14. @Override
  15. public void destroy() throws Exception
  16. {
  17. //Bean destruction code
  18. }
  19. }

2.2. 了解特定行为的接口

Spring 提供了一系列*Aware接口,这些接口允许 bean 向容器指示它们需要一定的基础结构依赖。 每个接口都将要求您实现一种将依赖项注入 bean 的方法。

这些接口可以概括为:

感知接口 覆盖方法 目的
ApplicationContextAware void setApplicationContext(ApplicationContext applicationContext) throws BeansException; 希望由其运行所要通知的ApplicationContext的任何对象实现的接口。
ApplicationEventPublisherAware void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher); 设置运行该对象的ApplicationEventPublisher
BeanClassLoaderAware void setBeanClassLoader(ClassLoader classLoader); 将 bean 类加载器提供给 bean 实例的回调。
BeanFactoryAware void setBeanFactory(BeanFactory beanFactory) throws BeansException; 将拥有的工厂提供给 Bean 实例的回调。
BeanNameAware void setBeanName(String name); 在创建此 bean 的 bean 工厂中设置 bean 的名称。
BootstrapContextAware void setBootstrapContext(BootstrapContext bootstrapContext); 设置该对象在其中运行的 BootstrapContext。
LoadTimeWeaverAware void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver); 设置此对象包含 ApplicationContext 的 LoadTimeWeaver。
MessageSourceAware void setMessageSource(MessageSource messageSource); 设置此对象在其中运行的 MessageSource。
NotificationPublisherAware void setNotificationPublisher(NotificationPublisher publisher); 为当前的托管资源实例设置NotificationPublisher实例。
PortletConfigAware void setPortletConfig(PortletConfig portletConfig); 设置运行该对象的 PortletConfig。
PortletContextAware void setPortletContext(PortletContext portletContext); 设置此对象在其中运行的 PortletContext。
ResourceLoaderAware void setResourceLoader(ResourceLoader resourceLoader); 设置运行该对象的 ResourceLoader。
ServletConfigAware void setServletConfig(ServletConfig servletConfig); 设置运行该对象的 ServletConfig。
ServletContextAware void setServletContext(ServletContext servletContext); 设置运行该对象的 ServletContext。

Java 程序展示了使用感知接口来控制字符串 bean 生命周期的用法。

DemoBean.java

  1. package com.howtodoinjava.task;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.beans.factory.BeanClassLoaderAware;
  4. import org.springframework.beans.factory.BeanFactory;
  5. import org.springframework.beans.factory.BeanFactoryAware;
  6. import org.springframework.beans.factory.BeanNameAware;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.context.ApplicationContextAware;
  9. import org.springframework.context.ApplicationEventPublisher;
  10. import org.springframework.context.ApplicationEventPublisherAware;
  11. import org.springframework.context.MessageSource;
  12. import org.springframework.context.MessageSourceAware;
  13. import org.springframework.context.ResourceLoaderAware;
  14. import org.springframework.context.weaving.LoadTimeWeaverAware;
  15. import org.springframework.core.io.ResourceLoader;
  16. import org.springframework.instrument.classloading.LoadTimeWeaver;
  17. import org.springframework.jmx.export.notification.NotificationPublisher;
  18. import org.springframework.jmx.export.notification.NotificationPublisherAware;
  19. public class DemoBean implements ApplicationContextAware,
  20. ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware,
  21. BeanNameAware, LoadTimeWeaverAware, MessageSourceAware,
  22. NotificationPublisherAware, ResourceLoaderAware
  23. {
  24. @Override
  25. public void setResourceLoader(ResourceLoader arg0) {
  26. // TODO Auto-generated method stub
  27. }
  28. @Override
  29. public void setNotificationPublisher(NotificationPublisher arg0) {
  30. // TODO Auto-generated method stub
  31. }
  32. @Override
  33. public void setMessageSource(MessageSource arg0) {
  34. // TODO Auto-generated method stub
  35. }
  36. @Override
  37. public void setLoadTimeWeaver(LoadTimeWeaver arg0) {
  38. // TODO Auto-generated method stub
  39. }
  40. @Override
  41. public void setBeanName(String arg0) {
  42. // TODO Auto-generated method stub
  43. }
  44. @Override
  45. public void setBeanFactory(BeanFactory arg0) throws BeansException {
  46. // TODO Auto-generated method stub
  47. }
  48. @Override
  49. public void setBeanClassLoader(ClassLoader arg0) {
  50. // TODO Auto-generated method stub
  51. }
  52. @Override
  53. public void setApplicationEventPublisher(ApplicationEventPublisher arg0) {
  54. // TODO Auto-generated method stub
  55. }
  56. @Override
  57. public void setApplicationContext(ApplicationContext arg0)
  58. throws BeansException {
  59. // TODO Auto-generated method stub
  60. }
  61. }

2.3. 自定义init()destroy()方法

可以通过两种方式定义 bean 配置文件中的默认initdestroy方法:

  • Bean 本地定义适用于单个 Bean
  • 全局定义适用于 bean 上下文中定义的所有 bean

2.3.1. Bean 本地定义

本地定义如下。

beans.xml

  1. <beans>
  2. <bean id="demoBean" class="com.howtodoinjava.task.DemoBean"
  3. init-method="customInit"
  4. destroy-method="customDestroy"></bean>
  5. </beans>

2.3.2. 全局定义

全局定义如下。 这些方法将为<beans>标签下给出的所有 bean 定义调用。 当您具有为所有 bean 一致定义通用方法名称(例如init()destroy())的模式时,它们很有用。 此功能可帮助您不必为所有 bean 单独提及initdestroy方法名称。

  1. <beans default-init-method="customInit" default-destroy-method="customDestroy">
  2. <bean id="demoBean" class="com.howtodoinjava.task.DemoBean"></bean>
  3. </beans>

显示在 bean XML 配置文件中配置的方法的 Java 程序。

DemoBean.java

  1. package com.howtodoinjava.task;
  2. public class DemoBean
  3. {
  4. public void customInit()
  5. {
  6. System.out.println("Method customInit() invoked...");
  7. }
  8. public void customDestroy()
  9. {
  10. System.out.println("Method customDestroy() invoked...");
  11. }
  12. }

2.4. @PostConstruct@PreDestroy

从 Spring 2.5 开始,您还可以使用注解来指定使用@PostConstruct@PreDestroy注解的生命周期方法。

  • @PostConstruct带注解的方法将在使用默认构造函数构造 Bean 之后,并且在实例返回给请求对象之前被调用。
  • 在即将在 bean 容器内销毁 bean 之前,将调用@PreDestroy带注解的方法。

Java 程序,用于显示注解配置的使用以控制注解的使用。

  1. package com.howtodoinjava.task;
  2. import javax.annotation.PostConstruct;
  3. import javax.annotation.PreDestroy;
  4. public class DemoBean
  5. {
  6. @PostConstruct
  7. public void customInit()
  8. {
  9. System.out.println("Method customInit() invoked...");
  10. }
  11. @PreDestroy
  12. public void customDestroy()
  13. {
  14. System.out.println("Method customDestroy() invoked...");
  15. }
  16. }

因此,这一切都与 Spring 容器内的 spring bean 生命周期有关。 记住给定的生命周期事件类型,这是一个常见的问题Spring 面试问题

学习愉快!