SpringBoot自动装配定义先后顺序失效原因极其解析

SpringBoot自动装配定义先后顺序失效原因极其解析

  • 1、场景分析
    • 1.1、问题总结
  • 2、使用`@AutoConfigureBefore`、`@AutoConfigureAfter`和`@AutoConfigureOrder`注解指定加载顺序
    • 2.2、@AutoConfigureXX注解失效原因总结
  • 3、使用静态内部装配类提升加载顺序
  • 4、bean加载顺序规则

1、场景分析

遇到的场景:
最近写定义依赖时,需要结合SpringMvcWebMvcConfigurationSupport扩展异常解析器方法extendHandlerExceptionResolvers

	@Beanpublic HandlerExceptionResolver handlerExceptionResolver(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();configureHandlerExceptionResolvers(exceptionResolvers);if (exceptionResolvers.isEmpty()) {addDefaultHandlerExceptionResolvers(exceptionResolvers, contentNegotiationManager);}extendHandlerExceptionResolvers(exceptionResolvers);HandlerExceptionResolverComposite composite = new HandlerExceptionResolverComposite();composite.setOrder(0);composite.setExceptionResolvers(exceptionResolvers);return composite;}

其中extendHandlerExceptionResolvers方法提供了可继承的接口,让开发者能够添加自定义的异常解析器放到HandlerExceptionResolverComposite中供dispatchServlet解析异常

1.1、问题总结

自定义的异常解析器配置类继承WebMvcConfigurationSupport类重写extendHandlerExceptionResolvers方法后,按照开放接口的原理,我们的异常解析器会添加到HandlerExceptionResolverComposite列表中,但是实际上并非如此。

  1. 开发者自定义的装配类和WebMvcConfigurationSupport引用的jar包中装配类顺序
  2. 解决方案一:使用@AutoConfigureBefore@AutoConfigureAfter@AutoConfigureOrder注解指定加载顺序
  3. 解决方案二:使用静态内部装配类提前加载

2、使用@AutoConfigureBefore@AutoConfigureAfter@AutoConfigureOrder注解指定加载顺序

SpringBoot下可以通过@Configuration自动扫描配置类和spring.factories来加载配置类,但这两种方式都无法控制加载顺序。

此时,可通过在配置类上增加@AutoConfigureAfter 、 @AutoConfigureBefore和@AutoConfigureOrder来控制配置文件加载的相对顺序。

SpringBoot的自动配置是通过spring.factories来指定的,它的优先级最低,加载时间最晚,spring.factories中的配置类顺序不代表实际加载顺序。可结合 @AutoConfigureAfter 和 @AutoConfigureBefore注解控制配置类的相对加载顺序。

通过@Configuration和@ComponentScan扫描加载的配置类,一般是我们自定义的配置类,这部分配置类优先级最高,加载时间最早,在加载spring.factories配置类前加载,但加载顺序不定。
这里就存在另一个易错点。简单的理解,当配置类在Spring扫描路径里面(scanBasePackages)会优先解析,后面在通过ImportSelector(spring.factories加载就是通过实现这个接口加载的配置类)加载进来的配置类就不会处理了,相当于一个类有两种加载方式,谁先加载谁就厉害。。。这里加载都会调用到processConfigurationClass()方法,这个下面会说!!!!

空口无凭上菜:ConfigurationClassParser–>doProcessConfigurationClass()方法加载顺序是@ComponentScan(扫描文件路径,路径里面元注解为@Component(@Cofiguration元注解也是@Component)都会被扫描到)—>加载@Import注解(配合ImportSelector接口)—>加载 @ImportResource—>加载@Bean—>…
大致顺序理清楚了。
也就是:通过spring.factories加载的配置类优先级更低,我们自定义的装配类最后才会加载

2.2、@AutoConfigureXX注解失效原因总结

extendHandlerExceptionResolvers方法在WebMvcConfigurationSupport加载的时候已经执行过了,由于加载顺序问题,那么我们自己的装配类中重写方法,将无法被调用;所以这就是@AutoConfigureBefore@AutoConfigureAfter@AutoConfigureOrder注解无法生效的原因,不适用很多场景

3、使用静态内部装配类提升加载顺序

这也是小编使用的方法,这种场景在纯Spring环境下我们几乎遇不见,缘由是在Spring下所有的配置文件都是我们手动确定和编写,所以“哪些能写、哪些不能写,哪些在前,哪些在后”均是确定的,由我们程序员自行控制。该场景在Spring Boot场景下被大量用到
在这里插入图片描述总结如下:

  • static加在bean注册方法上

1、 @Configuration配置类最优先被初始化,才会继续初始化其里面的@Bean;若有多个 @Configuration配置类,顺序由你构造AnnotationConfigApplicationContext时传入的顺序为准(若是被scan扫描进去的,则无序)


2、 @Bean方法上加static成为静态方法,并不能提升此Bean的优先级
主要是因为@Bean的解析,必须是发生在@Configuration配置类被实例化后,因此它并不能提升优先级

  • static加在静态内部类上

1、 @Configuration(外层)配置类的初始化顺序依旧是按照AnnotationConfigApplicationContext的定义顺序来的; 对于内部类的@Configuration的初始化(不管是静态还是非静态),也依旧是外部的@Configuration完成后才行
2、 内部类里的@Bean的优先级均高于外层定义的@Bean,同时可以看到static静态内部类能够提升优先级,它比非静态内部类的优先级还高
3、内部类有限原则它只作用于本@Configuration类,也就是说仅在本主类内提升优先级。另外若出现多个内部类,按照定义顺序执行(static永远高于非static哦)
4、 内部类的访问权限无所谓,private都行。

4、bean加载顺序规则

直接上干货了,测试代码太长啦;

SpringBoot2.7以后自动装配的定义文件该成了org.springframework.boot.autoconfigure.AutoConfiguration.imports
在这里插入图片描述

  • Spring.factories中定义的自动装配类优先级最低
  • 本类中bean顺序按依赖优先+代码顺序原则,比如A/B/C三个Bean上中下顺序写的代码,A依赖了C,所以C比A和B都提前加载
  • 跨类的bean加载顺序按照依赖优先+bean名称字母顺序加载
  • 静态内部类bean与跨类bean加载顺序一致

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

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

相关文章

矩阵起源加入 OpenCloudOS 操作系统开源社区,完成技术兼容互认证

近日&#xff0c;超融合异构云原生数据库 MatrixOne企业版软件 V1.0 完成了与 OpenCloudOS 的相互兼容认证&#xff0c;测试期间&#xff0c;整体运行稳定&#xff0c;在功能、性能及兼容性方面表现良好。 一、产品简介 矩阵起源 MatrixOrigin 致力于建设开放的技术开源社区和…

Nginx缓存基础

1 nginx缓存的流程 客户端需要访问服务器的数据时&#xff0c;如果都直接向服务器发送请求&#xff0c;服务器接收过多的请求&#xff0c;压力会比较大&#xff0c;也比较耗时&#xff1b;而如果在nginx缓存一定的数据&#xff0c;使客户端向基于nginx的代理服务器发送请求&…

Spring面试题:(五)Spring注解开发@Component,@Autowired,@Bean,@Configuration

Bean基本注解 spring提供注解的版本 Component注解替代bean标签 bean其它属性的相关注解&#xff1a; scope 替代scopelazy 替代lazy-initPostConstruct 替代init-methodPreDestroy 替代destroy-method 使用Component注解的前提是开启注解扫描 衍生注解Repository,Servi…

jdk安装

.概览 1.jdk下载 JDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK)。 安装JDK后&#xff0c;会在电脑中同时安装&#xff1a;java的运行环境jre 和 开发环境jdk。 安装 JDK时&#xff0c;不建议安装太旧或太新的版本。目前的最新版本是jdk9。目前jdk8比较稳定&am…

【Lin通信】LinTrcv配置及代码分析

目录 前言 正文 1.LinTrcv模块配置 1.1LinTrcvGeneral 1.2 LinTrcvChannel 1.2.1 LinTrcvAccess 1.2.1.1 LinTrcvDioAccess

STM32 LED编程 GPIO的初始化(标准库)

实验的电路图介绍 实验的电路图类似于开漏接法 要初始化GPIOC接口 标准库的模板 GPIO的标准库编程接口 GPIO引脚的初始化 GPIO作为片上外设 每一个片上外设使用前一定要使能时钟 为什么要使能时钟&#xff1f;时钟是啥 时钟的使能 stm32的每一个片上外设都是时序电路 时序…

go单元格测试

编写单元测试&#xff08;Unit Test&#xff09;是一种测试方法&#xff0c;用于验证代码中的单个功能单元&#xff08;通常是函数或方法&#xff09;是否按照预期工作。以下是编写单元测试的一般步骤&#xff1a; 1. 创建测试文件&#xff1a;在项目的测试目录中创建一个新的…

人类为什么要发明微积分?用Python实现微积分

很久很久以前&#xff0c;在一个宁静的小村庄中&#xff0c;住着一位名叫牛顿的年轻学者。牛顿对于周围的一切都充满好奇心&#xff0c;他喜欢仰望星空、观察植物生长&#xff0c;并经常思考自然界中的各种奥秘。 有一天&#xff0c;当他坐在庄园的苹果树下阅读书籍时&#xf…

如何改变Wi-Fi的IP地址,提高网络连接稳定性和速度

Wi-Fi已经成为我们日常生活中必不可少的一部分。大多数家庭和办公室都依赖于Wi-Fi来连接网络和进行各种在线活动。然而&#xff0c;有时我们可能会遇到网络连接不稳定或速度较慢的问题。这可能是由于IP地址的设置不当所导致的。虎观代理小二二将向您介绍如何改变Wi-Fi的IP地址&…

多数据源切换

多数据源切换 jdbcTemplate二级目录三级目录 jdbcTemplate使用切面mybatis层次的多数据源spring的dynamic自动注入 jdbcTemplate 二级目录 三级目录 项目中经常会有多个数据源&#xff0c;那么如何处理呢 有4种方法 准备&#xff1a; 创建两个数据库 CREATE SCHEMA test DE…

Django中如何创建表关系,请求生命周期流程图

Django中ORM创建表关系 如何创建表关系(一对一 &#xff0c; 一对多 &#xff0c; 多对多) 图书表&#xff0c;出版社表&#xff0c;作者表&#xff0c;作者详情表 换位思考法判断表关系 图书表和出版社表 >>> 一对多 >>> 图书表是多&#xff0c;出…

GCC工具详解【Linux知识贩卖机】

很多人在喧嚣声中登场&#xff0c;也有少数人在静默中退出。 --单独中的洞见2 文章目录 简介程序到可执行文件链接动态链接和静态链接动态库和静态库动态库和静态库的打包打包静态库打包动态库选项 -static 总结 简介 GCC&#xff08;GNU Compiler Collection&#xff09; 是一…

计算机中丢失mfc140u.dll怎么解决

mfc140u.dll是一个Microsoft Visual C库文件&#xff0c;主要用于MFC&#xff08;Microsoft Foundation Class&#xff09;应用程序的开发。它包含了MFC应用程序所需的一些常用功能&#xff0c;如对话框、窗口、菜单等。当mfc140u.dll丢失时&#xff0c;可能会导致MFC应用程序无…

思科9300交换机使用USB进行升级ISO

一、下载ISO 一、网址 Software Download - Cisco Systems 二、找到型号 四、选择XE 软件 五、进行下载 二、COPY 进 U盘 一、、请注意&#xff01;如果你的U盘不是Fat32文件格式则交换机读取不了&#xff0c;请先格式化再复制文件。 二、下载后将 bin文件复制到U盘。 1.扩展…

力扣labuladong——一刷day28

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、力扣380. O(1) 时间插入、删除和获取随机元素二、力扣710. 黑名单中的随机数 前言 常数时间删除-查找数组中的任意元素&#xff0c;且随机访问概率一致 如果…

idea Plugins 搜索不到插件

Settings — System Settings — HTTP Proxy&#xff0c;打开HTTP Proxy 页面&#xff0c;设置自动发现代理&#xff1a; 勾选Atuto-detect proxy settings&#xff0c;勾选Automatic proxy configuration URL&#xff0c;输入&#xff1a; https://plugins.jetbrains.com/id…

C语言 判断一个素数能被几个9整除

完整代码&#xff1a; // 判断一个素数能被几个9整除 //就是99...99%n0,n为那个素数 #include<stdio.h>int func(int n){//num是被除数就是99..9,i记录num有多少个9int num0,i0;//死循环while (1){i;numnum*109;//直到整除才跳出循环if (num%n0){//返回值为9的个数retu…

Unity 获取桌面路径的方法

在Unity中&#xff0c;当我们碰到以下一些情况时&#xff0c;可能需要桌面的路径。 1、文件操作&#xff1a;如果我们想在游戏中保存或读取文件到桌面&#xff0c;就可以使用桌面路径来指定文件的位置。 2、调试信息&#xff1a;在开发过程中&#xff0c;我们往往会将一些调试…

【Python】AppUI自动化—appium自动化元素定位、元素事件操作(17)下

文章目录 前言一.Appium 元素定位1.定位方式种类2.如何定位2.1 id定位2.2 className定位2.3 content-desc 定位2.4 Android Uiautomator定位4.1 text定位4.2 text模糊定位4.3 text正则匹配定位4.4 resourceId定位4.5 resourceId正则匹配定位4.6 className定位4.7 className正则…

No184.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…