当前位置: 首页 > news >正文

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 源码视频教程。

相关文章:

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

如果你脱口而出说添加 Order 注解或者是实现 Ordered 接口,那么恭喜,你掉坑了。 一 Order 注解和 Ordered 接口 在 Spring 框架中,Order 是一个非常实用的元注解,它位于 spring-core 包下,主要用于控制某些特定上下文…...

【学习笔记】Windows GDI绘图(十)Graphics详解(中)

文章目录 Graphics的方法AddMetafileComment添加注释BeginContainer和EndContainer新建、还原图形容器不指定指定源与目标矩形指定源与目标矩形 Clear清空并填充指定颜色CopyFromScreen截图CopyPixelOperation DrawImage绘制图像DrawImage的GraphicsDrawImageAbort回调ExcludeC…...

web学习笔记(六十二)

目录 1.键盘事件 2.KeepAlive 3.组件传值 3.1 兄弟组件传值 3.2 组件树传值 3.3 发布订阅者传值 1.键盘事件 keydown表示键盘事件&#xff0c;在不加修饰符的情况下&#xff0c;点击键盘上的任意位置都可以触发键盘事件&#xff0c; <template><div><!--…...

每天CTF小练一点--ctfshow年CTF

初一 题目&#xff1a; 2023是兔年&#xff0c;密码也是。聪明的小伙伴们&#xff0c;你能破解出下面的密码吗&#xff1f; 感谢大菜鸡师傅出题 flag格式是ctfshow{xxxxxx}.或许密码也有密码。 密文是&#xff1a; U2FsdGVkX1M7duRffUvQgJlESPfOTV2i4TJpc9YybgZ9ONmPk/RJje …...

Java Set接口 - TreeSet类

TreeSet 是 Java 集合框架中的一个类&#xff0c;它实现了 NavigableSet 接口&#xff0c;而 NavigableSet 是 SortedSet 接口的一个子接口。TreeSet 基于红黑树&#xff08;一种自平衡的二叉搜索树&#xff09;实现&#xff0c;因此它可以保证集合中的元素以升序排列。 以下是…...

css 理解了原理,绘制三角形就简单了

1.border-位置 注意&#xff1a;border-bottom/up/right/left 主要是以三角形的结构搭建而成&#xff0c;而border也是如此。而且从边框的外围开始计算像素尺寸。在理解了这一点之后&#xff0c;绘制三角形就简单多了。 1.transparent 注意&#xff1a;该属性主要是颜色透明…...

【JavaEE进阶】——MyBatis操作数据库 (#{}与${} 以及 动态SQL)

目录 &#x1f6a9;#{}和${} &#x1f388;#{} 和 ${}区别 &#x1f388;${}使用场景 &#x1f4dd;排序功能 &#x1f4dd;like 查询 &#x1f6a9;数据库连接池 &#x1f388;数据库连接池使⽤ &#x1f6a9;MySQL开发企业规范 &#x1f6a9;动态sql &#x1f388…...

电阻应变片的结构

电阻应变片的结构 常用的电阻应变片有金属应变片和半导体应变片两种。金属应变片分为体型和薄膜型。半导体应变片常见的有体型、薄膜型、扩散型、外延型、PN结及其他形式。图2—2所示为工程常见的应变片实物。 电阻应变片的典型结构如图2—3所示。它由敏感栅、基底、覆盖层和引…...

云原生时代:从 Jenkins 到 Argo Workflows,构建高效 CI Pipeline

作者&#xff1a;蔡靖 Argo Workflows Argo Workflows [ 1] 是用于在 Kubernetes 上编排 Job 的开源的云原生工作流引擎。可以轻松自动化和管理 Kubernetes 上的复杂工作流程。适用于各种场景&#xff0c;包括定时任务、机器学习、ETL 和数据分析、模型训练、数据流 pipline、…...

【数据库系统概论】事务

概述 在数据库系统中&#xff0c;事务&#xff08;Transaction&#xff09;是指一组作为单个逻辑工作单元执行的操作。这些操作要么全部成功&#xff08;提交&#xff09;&#xff0c;要么全部失败&#xff08;回滚&#xff09;。事务的主要目的是确保数据库的完整性和一致性&…...

C++-排序算法详解

目录 一. 冒泡排序&#xff1a; 二. 插入排序&#xff1a; 三. 快速排序&#xff1a; 四. 选择排序 五, 归并排序 六, 堆排序. 排序算法是一种将一组数据按照特定顺序&#xff08;如升序或降序&#xff09;进行排列的算法。 其主要目的是对一组无序的数据进行整理&#…...

Kotlin 引用(双冒号::)

文章目录 双冒号::引用函数普通函数成员函数类构造函数 引用变量&#xff08;很少用&#xff09;普通变量成员变量 双冒号:: Kotlin 中可以使用双冒号::对某一变量、函数进行引用。 Note&#xff1a;MyClass::class可用于获取KClass<MyClass>&#xff0c;此时的双冒号::…...

C++ day3练习

设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数。 #include <iostream>using namespace std;class Per{private:…...

命令模式(行为型)

目录 一、前言 二、命令模式 三、总结 一、前言 命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;命令模式将一个请求封装为一个对象&#xff0c;从而可以用不同的请求对客户进行参数化&#xff1b;对请求排队或记录请求日志&#xff0c;以…...

韩雪医生针药结合效果好 患者赠送锦旗表感谢

任先生长年献血身体出现不适&#xff0c;身上多处发黑发冷&#xff0c;伴随疼痛&#xff0c;而且还有慢性腹泻的症状。他曾前往苏州各大医馆做过检查&#xff0c;均查不出异常&#xff0c;但身体确实不舒服&#xff0c;面色晦暗。 后来他来到李良济&#xff0c;求诊于韩雪医生。…...

【队列、堆、栈 解释与区分】

文章目录 概要队列&#xff08;Queue&#xff09;定义特性应用场景 堆&#xff08;Heap&#xff09;定义特性应用场景 栈&#xff08;Stack&#xff09;定义特性应用场景 总结 概要 队列、堆和栈是三种常见的数据结构&#xff0c;它们各自具有不同的特性和应用场景。下面是对这…...

NTP网络时间服务器_安徽京准电钟

NTP网络时间服务器_安徽京准电钟 NTP网络时间服务器_安徽京准电钟 概述 NTP网络时间服务器是一款支持NTP和SNTP网络时间同步协议&#xff0c;高精度、大容量、高品质的高科技时钟产品。 NTP网络时间服务器设备采用冗余架构设计&#xff0c;高精度时钟直接来源于北斗、GPS系统中…...

Java:爬虫框架

一、Apache Nutch2 【参考地址】 Nutch 是一个开源Java 实现的搜索引擎。它提供了我们运行自己的搜索引擎所需的全部工具。包括全文搜索和Web爬虫。 Nutch 致力于让每个人能很容易, 同时花费很少就可以配置世界一流的Web搜索引擎. 为了完成这一宏伟的目标, Nutch必须能够做到…...

ChatGPT基本原理详细解说

ChatGPT基本原理详细解说 引言 在人工智能领域&#xff0c;自然语言处理&#xff08;NLP&#xff09;一直是研究的热点之一。随着技术的发展&#xff0c;我们见证了从简单的聊天机器人到复杂的语言模型的演变。其中&#xff0c;ChatGPT作为一项突破性技术&#xff0c;以其强大…...

Java日期时间处理深度解析:从Date、Calendar到SimpleDateFormat

粉丝福利&#xff1a;微信搜索「万猫学社」&#xff0c;关注后回复「电子书」&#xff0c;免费获取12本Java必读技术书籍。 Java中的日期和时间处理 在Java中&#xff0c;日期和时间的处理一直是一个复杂而繁琐的任务。那么&#xff0c;为什么会这样呢&#xff1f;让我们先来看…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...

32单片机——基本定时器

STM32F103有众多的定时器&#xff0c;其中包括2个基本定时器&#xff08;TIM6和TIM7&#xff09;、4个通用定时器&#xff08;TIM2~TIM5&#xff09;、2个高级控制定时器&#xff08;TIM1和TIM8&#xff09;&#xff0c;这些定时器彼此完全独立&#xff0c;不共享任何资源 1、定…...