Spring如何控制Bean的加载顺序

news2024/10/7 16:23:08

前言

正常情况下,Spring 容器加载 Bean 的顺序是不确定的,那么我们如果需要按顺序加载 Bean 时应如何操作?本文将详细讲述我们如何才能控制 Bean 的加载顺序。


场景

我创建了 4 个 Class 文件,分别命名为

  1. FirstInitialization

  2. SecondInitialization

  3. ThirdInitialization

  4. ForthInitialization

我希望这 4 个类按照 1、2、3、4 的顺序加载。

如下图,直接加载的话,顺序是 1、4、2、3,并不能达到要求。

如何控制

注意:网上很多文章说Order注解或Ordered接口可以控制 Bean 的加载顺序,其是并不能,它们的作用是定义 Spring IOC 容器中 Bean 定义类的执行顺序的优先级,并不是定义加载顺序。

使用@DependsOn 注解

在需要调整顺序的类上依次加@DependsOn注解,缺点是类过多的时候需要一个个加注解,且不好维护

@Component
public class FirstInitialization {
 
    @PostConstruct
    public void init(){
        System.out.println("我是第一个加载!");
    }
 
}

@Component
@DependsOn("firstInitialization")
public class SecondInitialization {
 
    @PostConstruct
    public void init(){
        System.out.println("我是第二个加载!");
    }
 
}

@Component
@DependsOn("secondInitialization")
public class ThirdInitialization {
 
    @PostConstruct
    public void init(){
        System.out.println("我是第三个加载!");
    }
 
}

@Component
@DependsOn("thirdInitialization")
public class ForthInitialization {
 
    @PostConstruct
    public void init(){
        System.out.println("我是第四个加载!");
    }
 
}

执行结果如下

基于 ApplicationContextInitializer 接口

接口简介

这里我简单介绍一个这个接口的用处, 等到整理到相关源码的时候再详细介绍。

ApplicationContextInitializer接口是在 Spring 容器刷新之前执行的一个回调函数。

执行时机:

  1. Spring 内部执行ConfigurableApplicationContext#refresh()方法前;

  2. SpringBoot 执行run()方法前。

一般有什么用呢?

在 SpringBoot 应用中 Classpath 上会有很多 jar 包,有些 jar 包需要在refresh()调用前对应用上下文做一些初始化动作,因此会提供ApplicationContextInitializer接口的实现类,放在如下图的文件中,这样会被SpringApplication#initialize发现,然后完成对应初始化。

实现步骤

首先创建一个类继承ApplicationContextInitializer接口。

public class MyApplicationContextInitializer implements ApplicationContextInitializer {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
 
        //将自定义的BeanFactoryPostProcessor实现类保存到ApplicationContext中
        applicationContext.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
    }
}

创建`META-INF/spring.factories`文件。

自定义`BeanDefinitionRegistryPostProcessor`。

/**
 * BeanFactoryPostProcessor的子类
 * 允许开发人员在Bean定义注册之前和之后对BeanDefinition进行自定义处理,例如添加,修改或删除Bean定义等。
 */
public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
 
    // 初始化需要排序的类,这里要保证插入顺序只能用LinkedHashMap
    private static final Map<String, Class> ORDER_BEAN_MAP = new LinkedHashMap<>() {
        {
            put("firstInitialization", FirstInitialization.class);
            put("secondInitialization", SecondInitialization.class);
            put("thirdInitialization", ThirdInitialization.class);
            put("forthInitialization", ForthInitialization.class);
        }
    };
 
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        Optional.ofNullable(ORDER_BEAN_MAP.keySet()).orElse(new HashSet<>()).stream()
                .forEach(beanName -> {
                    // 初始化一个 Bean 定义
                    AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
                            .genericBeanDefinition().getBeanDefinition();
 
                    // 按顺序注册每个Bean
                    beanDefinition.setBeanClass(ORDER_BEAN_MAP.get(beanName));
                    registry.registerBeanDefinition(beanName, beanDefinition);
                });
    }
}

执行结果如下

文章转载自:fuxing.

原文链接:https://www.cnblogs.com/fuxing/p/18181623

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

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

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

相关文章

2024年文化交流与综合艺术国际学术会议(ICCECA 2024)

2024年文化交流与综合艺术国际学术会议(ICCECA 2024) 2024 International Conference on Cultural Exchange and Comprehensive Art 一、【会议简介】 22024年文化交流与综合艺术国际学术会议&#xff0c;将汇集全球的艺术家和学者。 在这个盛大的学术会议上&#xff0c;来自世…

SQLServer数据库还原重命名

将备份的数据还原&#xff0c;因为数据库名冲突&#xff0c;需要将还原的数据库重命名 1.新建数据库&#xff0c;例如Test1 2.右键数据库-》任务-》还原&#xff0c;进入还原数据库界面 选择设备&#xff0c;然后找到还原数据库备份文件 3.点击文件选项&#xff0c;选中‘将所…

论文阅读:《Sequence can Secretly Tell You What to Discard》,减少推理阶段的 kv cache

目前各类大模型都支持长文本&#xff0c;例如 kimi chat 以及 gemini pro&#xff0c;都支持 100K 以及更高的上下文长度。但越长的上下文&#xff0c;在推理过程中需要存储的 kv cache 也越多。假设&#xff0c;数据的批次用 b 表示&#xff0c;输入序列的长度仍然用 s 表示&a…

Python专题:六、循环语句(1)

补充知识 代码的注释 #描述性文字 阅读代码的人更好的理解代码 while循环语句 x<100条件控制语句&#xff0c;Totalx,Total自增加x&#xff0c;x1&#xff0c;x自增加1&#xff0c;x<100此条件满足时&#xff0c;执行while循环&#xff0c;当x101时&#xff0c;x101条…

开源教程「动手学大模型应用开发」,从零基础到掌握大模型开发的关键技能!

LLM 正逐步成为信息世界的新革命力量&#xff0c;其通过强大的自然语言理解、自然语言生成能力&#xff0c;为开发者提供了新的、更强大的应用开发选择。随着国内外井喷式的 LLM API 服务开放&#xff0c;如何基于 LLM API 快速、便捷地开发具备更强能力、集成 LLM 的应用&…

JAVA文件的简单操作

文件IO&#xff08;Input和Output&#xff09; 文件的输入和输出是人为规定的&#xff0c;那么什么是输入&#xff1f;什么是输出捏&#xff1f;在这里统一已CPU为基准 例如&#xff1a;将文件由内存写入硬盘就是输出&#xff0c;有硬盘写入内存就是输入。可以总结为&#xff…

Mybatis-Plus常用的增删改查坑

添加依赖 <!--实体类上加上Data注解就不用写get&#xff0c;set&#xff0c;toString&#xff0c;equals等方法了--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional…

机器学习算法应用——K近邻分类器(KNN)

K近邻分类器&#xff08;KNN&#xff09;&#xff08;4-2&#xff09; K近邻分类器&#xff08;K-Nearest Neighbor&#xff0c;简称KNN&#xff09;是一种基本的机器学习分类算法。它的工作原理是&#xff1a;在特征空间中&#xff0c;如果一个样本在特征空间中的K个最相邻的样…

docker端口映射成功,docker端口不生效的问题解决,外界无法访问docker映射端口

docker端口映射不生效的问题解决 问题 使用docker run -p 88848:8848后&#xff0c;显示容器启动正常&#xff0c;并且使用docker logs –f xxx能够看到容器可以正常启用&#xff0c;docker ps 可以看到容器启动成功&#xff0c;并且端口已经映射,但是在浏览器访问相关地址&am…

05_SpringCloud

文章目录 SpringCloud服务调用的负载均衡Ribbon负载均衡 面向接口的服务调用OpenFeign 客户端FeignClient日志输出服务调用的超时设置 配置中心Nacos配置中心Nacos配置中心的使用Nacos配置的持久化 SpringCloud 服务调用的负载均衡 问题引出 // 服务发现List<ServiceInstan…

第十二届蓝桥杯省赛真题 Java C 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: ASC试题 B: 空间试题 C: 卡片试题 D: 相乘试题 E: 路径试题 F: 时间显示试题 G: 最少砝码试题 H : \mathrm{H}: H: 杨辉三角形试题 I: 左孩子右兄弟试题 J : \mathrm{J}: J: 双向排序 发现宝藏 前些天发现了一个巨牛的人工智能学习网站…

【SpringBoot篇】基于Redis分布式锁的 误删问题 和 原子性问题

文章目录 &#x1f354;Redis的分布式锁&#x1f6f8;误删问题&#x1f388;解决方法&#x1f50e;代码实现 &#x1f6f8;原子性问题&#x1f339;Lua脚本 ⭐利用Java代码调用Lua脚本改造分布式锁&#x1f50e;代码实现 &#x1f354;Redis的分布式锁 Redis的分布式锁是通过利…

傻傻分不清楚:JDK/JRE/JVM的区别和联系

在Java开发的世界里&#xff0c;JDK、JRE和JVM是三个经常听到的术语。 对于初学者来说&#xff0c;它们的概念和区别可能会让人感到困惑。 这篇文章详细解释下三个组件的含义、它们之间的区别和联系。 一&#xff0c;JDK&#xff1a;Java Development Kit JDK是Java开发工具…

umi6.x + react + antd的项目增加403(无权限页面拦截),404,错误处理页面

首先在src/pages下创建403&#xff0c;404&#xff0c;ErrorBoundary 403 import { Button, Result } from antd; import { history } from umijs/max;const UnAccessible () > (<Resultstatus"403"title"403"subTitle"抱歉&#xff0c;您无权…

shell-for循环语句练习题

1.计算从1到100所有整数的和 [rootlocalhost ~]# vim 1.sh #!/bin/bash sum0 #定义变量sum初始值为0 for i in {1..100} #for循环 i取值从1到100 do sum$[ isum ] #在每次循环中&#xff0c;变量i的值会依次取1到100的整数值。 #sum是一个累加器&#xff0c;初始值…

2024数维杯C题24页完整解题思路+1-4问代码解题+运行高清结果图

C题天然水合物资源量评价 点击链接加入群聊【2024数维杯数学建模ABC题资料汇总】&#xff1a; 2024数维杯C题完整思路24页配套代码1-4问后续参考论文https://www.jdmm.cc/file/2710638 下面内容是持续更新的 根据勘探数据确定天然气水合物资源的分布范围。 假设勘探区域内的…

Python深度学习基于Tensorflow(4)Tensorflow 数据处理和数据可视化

文章目录 构建Tensorflow.data数据集TFRecord数据底层生成TFRecord文件数据读取TFRecord文件数据图像增强 数据可视化 构建Tensorflow.data数据集 tf.data.Dataset表示一串元素&#xff08;element&#xff09;&#xff0c;其中每个元素包含一个或多个Tensor对象。例如&#xf…

【SVN-TortoiseSVN】SVN 的简介与TortoiseSVN 安装使用教程

目录 &#x1f31e;前言 &#x1f30a;1. SVN 的简介 &#x1f30d;1.1 SVN是什么 &#x1f30d;1.2 SVN 工作原理 &#x1f30d;1.3 TortoiseSVN 术语及定义 &#x1f30a;2. TortoiseSVN 安装与汉化 &#x1f30a;3. SVN 基本操作-TortoiseSVN &#x1f30d;3.1 浏览…

35个矩阵账号,如何通过小魔推打造2704万+视频曝光?

在如今的短视频时代&#xff0c;矩阵发布的作用被发挥到极致&#xff0c;通过各个短视频平台的流量分发&#xff0c;虽然视频质量不如那些头部的IP&#xff0c;但是在视频数量上却能做到轻松碾压&#xff0c;让自己的品牌与门店有更多的声量&#xff0c;这就是如今短视频平台对…

sbt安装

一、sbt介绍 在Spark中&#xff0c;sbt&#xff08;Scala Build Tool&#xff09;是一个用于构建Scala项目的工具。它是Spark项目的主要构建工具之一&#xff0c;用于编译Scala代码、管理依赖项、打包应用程序以及执行其他与项目构建相关的任务。 sbt的用途在Spark开发中主要…