Spring 中如何控制 Bean 的加载顺序?

如果你脱口而出说添加 @Order 注解或者是实现 Ordered 接口,那么恭喜,你掉坑了。

一 @Order 注解和 Ordered 接口

在 Spring 框架中,@Order 是一个非常实用的元注解,它位于 spring-core 包下,主要用于控制某些特定上下文中组件的执行顺序或排序,但它并不直接控制 Bean 的初始化顺序。

1.1 用途

@Order 注解或者是 Ordered 接口,常见的用途主要是两种:

  • 定义执行顺序:当多个组件(如拦截器、过滤器、监听器等)需要按照特定的顺序执行时,@Order 注解可以用来指定这些组件的执行优先级。数值越小,优先级越高,相应的组件会更早被执行或被放置在集合的前面(@Order 注解接受一个整数值,这个值可以是负数、零或正数。Spring 框架提供了 Ordered.HIGHEST_PRECEDENCE(默认最低优先级)和 Ordered.LOWEST_PRECEDENCE(默认最高优先级)常量,分别对应于 Integer.MIN_VALUE和 Integer.MAX_VALUE,可以方便地设定优先级。)。

  • 集合排序:当相同类型的组件被自动装配到一个集合中时,@Order 注解会影响它们在这个集合中的排列顺序。

1.2 使用场景

经典使用场景。

拦截器排序

在 Spring MVC 中,可以使用 @Order 来控制拦截器的执行顺序。

Spring Security Filters(过滤器)

在 Spring Security 中,过滤器链的顺序通过 @Order 来定义,确保正确的安全处理流程。这个在松哥最近的教程中和大家详细介绍过了。

Event Listeners(事件监听器)

当有多个监听同一事件的监听器时,可以通过 @Order 来控制它们的触发顺序。

Bean 的集合注入

当一个 Bean 依赖于一个特定类型的 Bean 集合时,带有 @Order 注解的 Bean 将按照指定顺序被注入。

可以看到,@Order 注解的使用场景中,主要是相同类型的 Bean 存在多个时,这多个 Bean 的执行顺序可以通过 @Order 注解或者实现 Ordered 接口来确定。

但是!!!

@Order 注解不控制初始化和加载@Order 注解不直接影响 Bean 的创建和初始化过程,这些由 Spring IoC 容器基于依赖关系和配置来决定。Spring IoC 容器根据依赖关系图来决定 Bean 的初始化顺序,而不是依据 @Order 注解。依赖关系决定了哪些 Bean 需要在其他 Bean 初始化之前被创建。

二 如何设置 Bean 的加载顺序?

有两种方式来设置 Bean 的加载顺序。

2.1 @DependsOn

@DependsOn 是 Spring 框架提供的一个注解,用于指示 Spring 容器在初始化一个 Bean 之前,必须先初始化其依赖的其他 Bean。这个注解可以帮助解决 Bean 间的依赖关系,确保依赖的 Bean 已经准备就绪。

@DependsOn 可以放在任何一个 Spring 管理的 Bean 定义上,包括但不限于配置类、服务类、数据访问对象等。其语法如下:

@DependsOn({"beanName1", "beanName2", ...})
public class MyBean {// ...
}

在这个例子中,MyBean 类声明了它依赖于名为 beanName1beanName2 的 Bean。这意味着,当 Spring 容器创建 MyBean 的实例时,它会首先确保 beanName1beanName2 已经被正确初始化。

相关的源码在 AbstractBeanFactory#doGetBean 方法中:

在创建的 Bean 的时候,先检查该 Bean 是否依赖了其他 Bean,如果依赖了,则先把其他 Bean 创建出来,然后再继续创建当前 Bean,这样就确保了 Bean 的加载顺序。

如果小伙伴们对这块的完整流程感兴趣,可以看松哥录制的 Spring源码分析。

2.2 BeanFactoryPostProcessor

第二种方式就是利用 BeanFactoryPostProcessor,BeanFactoryPostProcessor 的执行时机比较早,从下面这张流程图中可以看到,BeanFactoryPostProcessor 在正常的 Bean 初始化之前就执行了。

那么对于想要提前初始化的 Bean,我们可以在 BeanFactoryPostProcessor 中手动调用,类似下面这样:

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {//想要提前初始化的 Bean 在这里执行beanFactory.getBean("serviceB");}
}

三 小结

多个相同类型的 Bean 该如何确保其执行顺序?这个靠 @Order 注解或者 Ordered 接口来解决。但是这两者并不能解决 Bean 的加载顺序。Bean 的加载顺序有两种方式可以调整:

  1. 通过 @DependsOn 注解加载。
  2. 手动在 BeanFactoryPostProcessor#postProcessBeanFactory 方法中提前调用 getBean 方法去初始化 Bean。

如果小伙伴们想要彻底掌握 Spring 源码,那么不妨看看松哥录制的 Spring 源码视频教程。

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

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

相关文章

SQL实验 带函数查询和综合查询

一、实验目的 1.掌握Management Studio的使用。 2.掌握带函数查询和综合查询的使用。 二、实验内容及要求 1.统计年龄大于30岁的学生的人数。 --统计年龄大于30岁的学生的人数。SELECT COUNT(*) AS 人数FROM StudentWHERE (datepart(yea…

小公司的软件开发IT工具箱

目录 工具链困境 难题的解决 达到的效果 资源要求低 工具箱一览 1、代码管理工具 2、自动化发版(测试)工具 3、依赖库(制品包)管理 4、镜像管理 5、授权管理(可选) 待讨论:为什么不是…

基于全志T507-H的Linux-RT实时性测试案例分享

本文将为各位工程师演示全志T507-H工业评估板(TLT507-EVM)基于IgH EtherCAT控制伺服电机方法,生动说明Linux-RT Igh EtherCAT的强大之处! Linux-RT系统的优势 内核开源、免费、功能完善。 RT PREEMPT补丁,使Linux内…

【Qt】对话框

文章目录 1 :peach:对话框介绍:peach:2 :peach:对话框的分类:peach:2.1 :apple:模态对话框:apple:2.2 :apple:非模态对话框:apple:2.3 :apple:混合属性对话框:apple: 3 :peach:Qt 内置对话框:peach:3.1 :apple:消息对话框 QMessageBox:apple: 1 🍑对话框介绍&#x…

AK F.*ing leetcode 流浪计划之费马小定理与组合数取模

欢迎关注更多精彩 关注我,学习常用算法与数据结构,一题多解,降维打击。 费马小定理与证明 参考 https://zhuanlan.zhihu.com/p/594859227 费马小定理:如果p是一个质数,而正整数a不是p的倍数,那么a(p-1)≡…

LabVIEW齿轮调制故障检测系统

LabVIEW齿轮调制故障检测系统 概述 开发了一种基于LabVIEW平台的齿轮调制故障检测系统,实现齿轮在恶劣工作条件下的故障振动信号的实时在线检测。系统利用LabVIEW的强大图形编程能力,结合Hilbert包络解调技术,对齿轮的振动信号进行精确分析…

opensips 3.5的DB部署

opensips 3.X的DB部署方式较之前版本有很大的不同。本文以opensips 3.5 为例,说明部署的过程。 当OpenSIPS安装完成后,需要进一步做什么?最大的可能就是部署配套的DB。因为很多功能离不开它,比如用户鉴权、注册信息持久化、dialog…

MySQL学习——影响选项文件处理的命令行选项和程序选项修改器

大多数支持选项文件的MySQL程序都处理以下选项。因为这些选项会影响选项文件的处理,所以必须在命令行上给出,而不是在选项文件中给出。为了正常工作,这些选项中的每一个都必须先于其他选项给出,但以下情况除外: -prin…

OpenCASCADE开发指南<十四>:OCCT建模类之BRepPrimAPI_MakePipe创建管道

1、OpenCasCade拓扑几何 在Open CASCADE Technology (OCCT) 中,除了基本三维几何体建模类BRepBuilderAPI外,还提供了复杂模型的建模类,常用的有如下几种,他们可以单独使用或相互组合,通过OCCT提供的融合函数进行组装。例如:BRepOffsetAPI_ThruSections、BRepOffsetAPI_Ma…

sqlite基本操作

简介 文章目录 简介1.数据库的安装2.数据库命令:API,创建表单代码 csprintf()getchar和scanf() 1.数据库的安装 sudo dpkg -i *.deb这个报错表明出现依赖问题 用这个命令后再试试sudo apt --fix-broken in…

Docker是什么?使用场景作用及Docker的安装和启动详解

目录 Docker是什么? Docker的发展 Docker的安装 Docker使用 Docker的运行机制 第一个Docker容器 进入Docker容器 客户机访问容器 Docker是什么? Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker …

ChatGPT的基本原理是什么?又该如何提高其准确性?

在深入探索如何提升ChatGPT的准确性之前,让我们先来了解一下它的工作原理吧。ChatGPT是一种基于深度学习的自然语言生成模型,它通过预训练和微调两个关键步骤来学习和理解自然语言。 在预训练阶段,ChatGPT会接触到大规模的文本数据集&#x…

绘画参数配置及使用

绘画参数配置及使用 路径:站点后台-功能-AI绘画 进入参数配置 接口选择:多种接口自主选择(需自己准备key),对应接口的key对话和绘画通用 存储空间: 位置在超管后台-存储空间 自主选择存储(需…

冯喜运:6.3周一黄金原油行情分析及操作建议

【黄金消息面分析】:上周行情概述:现货黄金上周(0527-0531)反弹上探,5月27号开盘前本人曾提醒关注反弹,较当时上涨约30美元,最高至2364一线,其后震荡下跌。周线小幅收跌0.27%&#x…

微服务:Rabbitmq的WorkQueue模型的使用、默认消费方式(消息队列中间件)

文章目录 WorkQueue模型控制预取消息个数 WorkQueue模型 当然,一个队列,可以由多个消费者去监听。 来实现一下. 生产者: Testpublic void testWorkQueue() throws InterruptedException {// 队列名称String queueName "simple.queue…

通过提示工程将化学知识整合到大型语言模型中

在当今快速发展的人工智能领域,大型语言模型(LLMs)正成为科学研究的新兴工具。这些模型以其卓越的语言处理能力和零样本推理而闻名,为解决传统科学问题提供了全新的途径。然而,LLMs在特定科学领域的应用面临挑战&#…

力扣173题:二叉搜索树迭代器(含模拟面试)

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容,和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣! 推荐:数据分析螺丝钉的首页 关注微信公众号 数据分析螺丝钉 免费领取价值万元的python/java/商业…

蓝奏管理器iapp源码V3

蓝奏登录注册,简单管理文件夹等都没问题,就是上传接口需要有能力的人抓包进行修复一下(我留了之前还能正常使用的接口,也是蓝奏官方的,所以参照一下就行。),这个应该也不是什么大问题&#xff0…

【自然语言处理】【Scaling Law】Observational Scaling Laws:跨不同模型构建Scaling Law

相关博客 【自然语言处理】【Scaling Law】Observational Scaling Laws:跨不同模型构建Scaling Law 【自然语言处理】【Scaling Law】语言模型物理学 第3.3部分:知识容量Scaling Laws 【自然语言处理】Transformer中的一种线性特征 【自然语言处理】【大…

Ansible04-Ansible Vars变量详解

目录 写在前面6 Ansible Vars 变量6.1 playbook中的变量6.1.1 playbook中定义变量的格式6.1.2 举例6.1.3 小tip 6.2 共有变量6.2.1 变量文件6.2.1.1 变量文件编写6.2.1.2 playbook编写6.2.1.3 运行测试 6.2.2 根据主机组使用变量6.2.2.1 groups_vars编写6.2.2.2 playbook编写6.…