3.sping掌握Bean生命周期

在Spring框架中,Bean的生命周期指的是从Bean被创建到销毁的整个过程。掌握Bean的生命周期对于开发者来说非常重要,因为它可以帮助开发者更好地理解Spring如何管理Bean,以及如何在Bean的不同阶段插入自定义逻辑。以下是Bean生命周期的主要阶段:

实例化Bean: Spring容器首先通过反射机制实例化Bean,这是Bean生命周期的开始。

设置Bean属性: 在Bean实例化之后,Spring容器会注入Bean的属性,这些属性可能是通过XML配置、注解或Java配置指定的。

处理BeanNameAware和BeanFactoryAware:

BeanNameAware: 如果Bean实现了BeanNameAware接口,Spring将调用setBeanName()方法,传入Bean的ID。
BeanFactoryAware: 如果Bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,传入BeanFactory容器的引用。
BeanPostProcessor前置处理: 在Bean的属性设置之后,Spring会调用所有的BeanPostProcessor的postProcessBeforeInitialization()方法。

初始化Bean:

InitializingBean: 如果Bean实现了InitializingBean接口,Spring将调用afterPropertiesSet()方法。
自定义初始化方法: 如果Bean配置了init-method属性,Spring将调用指定的初始化方法。
BeanPostProcessor后置处理: 在Bean初始化之后,Spring会调用所有的BeanPostProcessor的postProcessAfterInitialization()方法。这个方法可以在Bean初始化之后进行一些额外的处理。

**使用Bean:**此时Bean已经准备好被应用程序使用了,Spring容器将Bean放入缓存,以供应用程序多次调用。

处理DisposableBean和自定义销毁方法:

DisposableBean: 如果Bean实现了DisposableBean接口,Spring将调用destroy()方法。
自定义销毁方法: 如果Bean配置了destroy-method属性,Spring将调用指定的销毁方法。
销毁Bean: 当Spring容器关闭时,它会销毁所有的Bean。对于单例Bean,销毁时机是在容器关闭时;对于原型Bean,销毁时机是在Bean不再被使用时。

了解Bean的生命周期对于开发者来说非常重要,因为它允许开发者在Bean的不同阶段插入自定义逻辑,例如在Bean初始化前后执行特定的操作,或者在Bean销毁前清理资源。通过实现特定的接口或配置特定的方法,开发者可以控制Bean的创建和销毁过程。

初始化InitializingBean/@PostConstruct

在Spring框架中,InitializingBean接口和@PostConstruct注解都是用来指定Bean初始化方法的。它们都是在Bean的属性设置完成之后,由Spring容器调用,以执行一些初始化逻辑。下面是它们各自的使用方式和区别:

InitializingBean接口
InitializingBean是一个由Spring提供的接口,它定义了一个afterPropertiesSet()方法。如果一个Bean实现了这个接口,Spring容器在设置完Bean的属性后会自动调用这个方法。这个方法可以用来执行一些初始化逻辑,比如资源的初始化、服务的启动等。

public class MyBean implements InitializingBean {
// 其他属性和方法

@Override
public void afterPropertiesSet() {// 初始化逻辑
}

}
@PostConstruct注解
@PostConstruct是一个注解,它标记在Bean的某个方法上,表示这个方法应该在Bean的属性设置完成之后,依赖注入完成之后,但在Bean准备使用之前被调用。这个方法通常也用于执行初始化逻辑。

public class MyBean {
// 其他属性和方法

@PostConstruct
public void initMethod() {// 初始化逻辑
}

}
区别和选择
使用方式:InitializingBean需要实现一个接口,而@PostConstruct是一个注解,可以更灵活地应用于任何方法。
灵活性:@PostConstruct注解提供了更高的灵活性,因为它可以应用于任何方法,而不需要实现额外的接口。
顺序:在Spring中,实现了InitializingBean接口的afterPropertiesSet()方法和使用@PostConstruct注解的方法都会在Bean的属性设置之后被调用,但@PostConstruct注解的方法可能会在afterPropertiesSet()之前调用,具体顺序取决于Bean的创建顺序。
JSR-250规范:@PostConstruct是JSR-250规范的一部分,它提供了一种与Spring框架无关的初始化Bean的方式。这意味着即使在没有Spring的环境中,也可以使用@PostConstruct。
通常情况下,推荐使用@PostConstruct注解,因为它提供了更好的灵活性,并且与Spring框架无关,可以在其他支持JSR-250规范的容器中使用。然而,如果你的Bean已经实现了InitializingBean接口,那么继续使用afterPropertiesSet()方法也是可行的。

Bean的后置处理器BeanPostProcessor源码分析

Spring框架中的BeanPostProcessor是一个非常重要的接口,它允许开发者在容器初始化Bean的前后插入自定义逻辑。BeanPostProcessor接口定义了两个方法:

postProcessBeforeInitialization(Object bean, String beanName): 在Bean的初始化方法调用之前调用。
postProcessAfterInitialization(Object bean, String beanName): 在Bean的初始化方法调用之后调用。
以下是BeanPostProcessor接口的源码示例:

public interface BeanPostProcessor {

/*** 在调用初始化方法之前,调用注册的BeanPostProcessors。* @param bean 原始bean实例* @param beanName bean的名称* @return 返回的可能是包装的或者替换的bean实例* @throws org.springframework.beans.BeansException*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;/*** 在调用初始化方法之后,调用注册的BeanPostProcessors。* @param bean 原始bean实例* @param beanName bean的名称* @return 返回的可能是包装的或者替换的bean实例* @throws org.springframework.beans.BeansException*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
源码分析
在Spring容器的初始化过程中,BeanPostProcessor的逻辑主要在AbstractApplicationContext类中实现。以下是源码分析的关键点:

注册BeanPostProcessor: 在容器初始化时,所有的BeanPostProcessor实现类都会被注册到容器中。

调用postProcessBeforeInitialization: 在Bean的初始化方法afterPropertiesSet或自定义的初始化方法执行之前,容器会遍历所有的BeanPostProcessor,并调用它们的postProcessBeforeInitialization方法。

调用postProcessAfterInitialization: 在Bean的初始化方法执行之后,容器会再次遍历所有的BeanPostProcessor,并调用它们的postProcessAfterInitialization方法。

返回可能被替换的Bean: BeanPostProcessor的两个方法都返回一个Object类型的实例。这意味着,开发者可以在BeanPostProcessor中修改原始Bean的实例,或者返回一个新的实例来替换原始Bean。

异常处理: 如果在BeanPostProcessor的调用过程中抛出了异常,容器会捕捉这个异常,并传播出去。

应用顺序: BeanPostProcessor的实现类可以定义它们的应用顺序。如果需要,可以通过实现Ordered接口或使用@Order注解来指定顺序。

示例
下面是一个简单的BeanPostProcessor实现示例,它在Bean初始化前后打印日志:

public class MyBeanPostProcessor implements BeanPostProcessor {

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("Before initializing bean: " + beanName);return bean; // 或者返回一个新的实例
}@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("After initializing bean: " + beanName);return bean; // 或者返回一个新的实例
}

}
通过实现BeanPostProcessor接口,开发者可以在Spring容器管理Bean的生命周期中插入自定义逻辑,这为AOP、事务管理等高级特性的实现提供了基础。

销毁DisposableBean/@PreDestroy

在Spring框架中,DisposableBean接口和@PreDestroy注解都用于处理Bean的销毁逻辑,即在Bean生命周期结束时执行的清理工作。以下是它们各自的使用方式和特点:

DisposableBean接口
DisposableBean是一个由Java EE规范定义的接口,Spring也实现了这个接口。它包含一个destroy()方法,用于执行Bean销毁时的清理工作。如果一个Bean实现了DisposableBean接口,Spring容器在销毁Bean之前会自动调用这个方法。

public class MyBean implements DisposableBean {
// 其他属性和方法

@Override
public void destroy() {// 销毁逻辑
}

}
@PreDestroy注解
@PreDestroy是一个注解,它标记在Bean的某个方法上,表示这个方法应该在Bean销毁之前被调用。这个方法通常用于执行清理逻辑,如关闭数据库连接、停止运行的线程等。

public class MyBean {
// 其他属性和方法

@PreDestroy
public void preDestroyMethod() {// 销毁逻辑
}

}
区别和选择
使用方式:DisposableBean需要实现一个接口,而@PreDestroy是一个注解,可以更灵活地应用于任何方法。
灵活性:@PreDestroy提供了更高的灵活性,因为它可以应用于任何方法,而不需要实现额外的接口。
JSR-250规范:@PreDestroy是JSR-250规范的一部分,它提供了一种与Spring框架无关的销毁Bean的方式。这意味着即使在没有Spring的环境中,也可以使用@PreDestroy。
销毁顺序:在Spring中,实现了DisposableBean接口的destroy()方法和使用@PreDestroy注解的方法都会在Bean销毁时被调用,但具体顺序取决于Spring容器的管理方式和其他Bean销毁逻辑的配置。
通常情况下,推荐使用@PreDestroy注解,因为它提供了更好的灵活性,并且与Spring框架无关,可以在其他支持JSR-250规范的容器中使用。然而,如果你的Bean已经实现了DisposableBean接口,那么继续使用destroy()方法也是可行的。

销毁流程
在Spring容器关闭时,它会遍历所有的Bean,并调用它们的销毁逻辑。销毁流程通常包括以下步骤:

调用DisposableBean的destroy()方法。
调用带有@PreDestroy注解的方法。
如果Bean配置了destroy-method属性,调用指定的销毁方法。
通过实现DisposableBean接口或使用@PreDestroy注解,开发者可以在Bean销毁时执行必要的清理工作,确保资源得到正确释放。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/35936.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

802.11漫游流程简单解析与笔记_Part2_02_wpa_supplicant、cfg80211、nl80211内核与驱动的关系

wpa、cfg80211、nl80211内核与驱动的关系示意图如下: nl80211和cfg80211都是内核定义的标准接口,目的是规范驱动和应用的统一调用,wpa中常出现nl80211就是通过内核的nl80211接口调用对应cfg80211的部分,进而控制驱动收发数据或切换…

AI技术与艺术的融合:开创性的用户界面与产品体验

引言 近年来,人工智能(AI)的飞速发展改变了我们的生活和工作方式。AI技术不仅在算力和模型上取得了重大进步,更在用户界面和产品体验方面迎来了突破。近日,科技博客 Stratechery 的文章以及硅谷投资基金 AI Grant 的两…

高频面试题基本总结回顾2(含笔试高频算法整理)

干货分享,感谢您的阅读! (暂存篇---后续会删除,完整版和持续更新见高频面试题基本总结回顾(含笔试高频算法整理)) 备注:引用请标注出处,同时存在的问题请在相关博客留言…

没有采用框架的LeSS导入

我提倡在使用LeSS中平衡框架导向和实验导向。因为框架导向已经挺强了,我想更多地展开实验导向。有可能不采用LeSS框架来导入LeSS吗?我认为是可能的,因为那其实就是受LeSS实验启发的持续改进。 受LeSS实验启发的持续改进 让我来分两部分加以…

Docker 命令——安全

我们将学习两个命令。第一个命令是 docker container run 命令,这样你就能看到使用该命令的一些好处。其次,我们将看看 docker container diff 命令,你可以用它来查看在已有的镜像基础上做了什么。让我们看看如何使用这两个命令来确保容器的安…

补充:二分类器实现多分类 --- 一对一与一对多策略

文章目录 前言一、一对多(One-vs-Rest, OvR)1 理论2 决策原则(这里给出的是SVM的,其他的二分类器也类似)2 简单代码演示二、 一对一(One-vs-One, OvO)1 理论2 决策原则(投票)3 简单代码演示总结前言 我在大三刚接触到机器学习课程的时候,回归问题很自然就能跨过这个…

深度学习在蛋白质结构预测的新突破:AlphaFold、RoseTTAFold与ESMFold

在蛋白质结构预测和功能预测领域,基于机器学习的方法最近取得了显著的进展。特别是深度学习技术在这个领域中展现出了强大的能力,代表性的技术有 DeepMind 的 AlphaFold 和 RoseTTAFold。这些技术利用了大量的生物数据和先进的神经网络架构,极…

调试代码Pair-wise-Similarity-module-master

第一步:运行.py文件生成json文件 问题一:json.decoder.JSONDecodeError: Invalid \escape: line 1 column 31616 (char 31615) 解决: for dataset in dataset_list:with open(datasetmap[dataset] ".csv", "r") as li…

什么是Arkose Labs挑战及其解决方法

Arkose Labs挑战是一种复杂的机制,旨在验证用户是真正的人类,而不是自动化的机器人或脚本。这一挑战在维护在线服务的安全性和完整性方面发挥着关键作用,通过防止欺诈活动并确保只有真实用户才能访问某些功能。 目录 什么是Arkose Labs挑战&a…

Python 基础 (标准库):堆 heap

1. 官方文档 heapq --- 堆队列算法 — Python 3.12.4 文档 2. 相关概念 堆 heap 是一种具体的数据结构(concrete data structures);优先级队列 priority queue 是一种抽象的数据结构(abstract data structures)&…

分布式锁(3):jedis基于Redis set命令的分布式锁

1 实现思路 获取锁的时候,使用 setnx 加锁,并使用 expire 命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的 value 值需要指定,可以根据具有业务含义,本文简化为 UUID,在释放锁的时候进行判断,避免误释放。获取锁的时候还设置一个获取的超时时间,若超过这个时间…

A34 STM32_HAL库函数 之 PCCARD通用驱动 所有函数的介绍及使用

A34 STM32_HAL库函数 之 PCCARD通用驱动 所有函数的介绍及使用 1 该驱动函数预览1.1 HAL_PCCARD_Init1.2 HAL_PCCARD_DeInit1.3 HAL_PCCARD_MspInit1.4 HAL_PCCARD_MspDeInit1.5 HAL_PCCARD_Read_ID1.6 HAL_PCCARD_Read_Sector1.7 HAL_PCCARD_Write_Sector1.8 HAL_PCCARD_Erase…

微信小程序-自定义组件checkbox

一.自定义Coponent组件 公共组件:将页面内公共的模块抽取为自定义组件,在不同页面复用。 页面组件:将复杂页面进行拆分,降低耦合度,有利于代码维护。 可以新建文件夹component放组件: 组件名为custom-che…

【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验3 总线型以太网的特性(广播,竞争总线,冲突)

一、实验目的 1.验证总线型以太网的特性; 2.验证广播特性; 3.验证各主机对总线的竞争使用以及可能产生的碰撞。 二、实验要求 1.使用Cisco Packet Tracer仿真平台; 2.观看B站湖科大教书匠仿真实验视频,完成对应实验。 三、实验内容…

PatchMixer:一种用于长时间序列预测的Patch混合架构

前言 《PatchMixer: A Patch-Mixing Architecture for Long-Term Time Series Forecasting》原文地址,Github开源代码地址GitHub项目地址Some-Paper-CN。本项目是译者在学习长时间序列预测、CV、NLP和机器学习过程中精读的一些论文,并对其进行了中文翻译…

小抄 20240624

1 不要拿自己的短板和别人的长板比。 看到别人的长板,可以学习,不要因为暂时达不到而自卑,长板能成长板,都是经过长期的刻意练习才达到的。 要在认识到自己长板的基础上,以长板为主,适当补充短板&#x…

软件测试学习笔记丨JUnit5执行顺序

本文转自测试人社区,原文链接: https://ceshiren.com/t/topic/28025 指定顺序使用场景 测试用例有业务逻辑相关集成测试(主流程测试) 排序方式 方法排序类排序Suite官方网站没有明确说明默认排序的具体规则 方法排序的类型 方法排序-Order 注解指定排序 …

python中的nan是什么意思

NaN(not a number),在数学表示上表示一个无法表示的数,这里一般还会有另一个表述inf,inf和nan的不同在于,inf是一个超过浮点表示范围的浮点数(其本质仍然是一个数,只是他无穷大&…

C#语法——ref和out关键字的使用

前言 我们在C#开发中经常需要将一个参数传入一个方法,然后在方法内部改变这个参数的值,如果这个参数是引用类型,那么直接在方法中改变该参数的值,方法执行完以后该参数的值也会被改变;如果这个参数是值类型&#xff0…

利用ChatGPT优化程序员工作流程:实用案例分享

近年来,人工智能技术的迅猛发展给各行各业带来了翻天覆地的变化。作为其中的一员,程序员在工作中也受益匪浅。其中,ChatGPT的出现,更是成为优化程序员工作流程的得力助手。本文将通过多个实用案例,分享如何利用ChatGPT…