05-Spring之Bean生命周期源码解析(下)

本文详细介绍了Spring容器在关闭时Bean的销毁过程,包括如何判断和适配DisposableBean,以及清理相关资源的步骤。在Bean销毁时,Spring会检查Bean是否实现了DisposableBean接口、AutoCloseable接口或设置了destroyMethod,通过适配器模式将这些Bean转换为DisposableBeanAdapter以调用销毁方法。此外,文章还提到了在容器关闭时的事件发布和单例Bean的销毁流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Bean的销毁过程

Bean销毁是发送在Spring容器关闭过程中的。

在Spring容器关闭时,比如:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();

// 容器关闭
context.close();

在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是DisposableBean:

  1. 当前Bean是否实现了DisposableBean接口
  2. 或者,当前Bean是否实现了AutoCloseable接口
  3. BeanDefinition中是否指定了destroyMethod
  4. 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
    1. ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean
    2. InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是DisposableBean
  5. 把符合上述任意一个条件的Bean适配成DisposableBeanAdapter对象,并存入disposableBeans中(一个LinkedHashMap)

在Spring容器关闭过程时:

  1. 首先发布ContextClosedEvent事件
  2. 调用lifecycleProcessor的onCloese()方法
  3. 销毁单例Bean
    1. 遍历disposableBeans
      1. 把每个disposableBean从单例池中移除
      2. 调用disposableBean的destroy()
      3. 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean
      4. 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉 (inner bean参考https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-inner-beans)
    2. 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanName
    3. 清空allBeanNamesByType,是一个Map,key是bean类型,value是该类型所有的beanName数组
    4. 清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例Bean

这里涉及到一个设计模式:适配器模式

在销毁时,Spring会找出实现了DisposableBean接口的Bean。

但是我们在定义一个Bean时,如果这个Bean实现了DisposableBean接口,或者实现了AutoCloseable接口,或者在BeanDefinition中指定了destroyMethodName,那么这个Bean都属于“DisposableBean”,这些Bean在容器关闭时都要调用相应的销毁方法。

所以,这里就需要进行适配,将实现了DisposableBean接口、或者AutoCloseable接口等适配成实现了DisposableBean接口,所以就用到了DisposableBeanAdapter。

会把实现了AutoCloseable接口的类封装成DisposableBeanAdapter,而DisposableBeanAdapter实现了DisposableBean接口。

SpringBean生命周期源码主要涉及到Bean的初始化、依赖注入、后置处理、销毁等各个阶段。以下是一个简化的Spring Bean生命周期源码解析: 1. 实例化(Instantiation):Spring通过反射机制实例化Bean对象。这是通过调用构造函数或者工厂方法来完成的。 2. 属性注入(Property Injection):在实例化后,Spring将通过依赖注入(Dependency Injection)来设置Bean的属性值。这是通过调用setter方法或者直接访问字段来完成的。 3. Aware接口回调:Spring会检查Bean是否实现了某些Aware接口(如BeanNameAware、ApplicationContextAware等),并通过回调方法将相关的信息注入到Bean中。 4. BeanPostProcessor前置处理(BeanPostProcessor Pre-Initialization):Spring会检查是否有注册的BeanPostProcessor,如果有,则在Bean初始化前调用它们的postProcessBeforeInitialization方法。 5. 初始化(Initialization):初始化阶段包括两个步骤: a. 调用自定义的初始化方法(如通过@PostConstruct注解标记的方法或实现了InitializingBean接口的afterPropertiesSet方法)。 b. 调用BeanPostProcessor后置处理方法postProcessAfterInitialization。 6. 使用(In Use):此时Bean已经初始化完成,可以使用了。 7. 销毁(Destruction):在容器关闭或者手动销毁时,Spring会调用销毁方法来释放Bean占用的资源。 a. 调用自定义的销毁方法(如通过@PreDestroy注解标记的方法或实现了DisposableBean接口的destroy方法)。 b. 调用BeanPostProcessor后置处理方法postProcessBeforeDestruction。 以上是简化的Spring Bean生命周期源码解析,实际的源码会更加复杂和详细。Spring通过BeanPostProcessor和各种回调接口,提供了丰富的扩展点和生命周期管理功能,使开发者能够在Bean的不同阶段进行自定义操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值