栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

@AutoConfigureBefore注解的失效分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

@AutoConfigureBefore注解的失效分析

  • 问题描述:现有三个配置类,通过@AutoConfigureBefore注解保证加载顺序依次为 EncryptionPropertyConfig ApiAutoConfiguration RedisAutoConfiguration 。

  • 实际情况:加载顺序为 ApiAutoConfiguration RedisAutoConfiguration EncryptionPropertyConfig,

  • 其中ApiAutoConfiguration 和 RedisAutoConfiguration 的加载顺序遵从@AutoConfigureBefore注解控制,可以自由调整顺序,但EncryptionPropertyConfig不论如何配置,都无法在其他两个配置之前加载。

按照 使用@AutoConfigureBefore调整配置顺序竟没生效 中的描述,自动扫描路径下的配置加载优先级更高,但实测,把EncryptionPropertyConfig 放在自动扫描路径下,依然晚于其他两个配置加载。

自定义配置类,测试加载顺序,任意调控顺序,结果都符合 预期。

所以可以推测,ApiAutoConfiguration 和 RedisAutoConfiguration 有问题,这两个配置类的优先级明显比其他配置类高一档,但两者之间属于同一档。

ApiAutoConfiguration 和 RedisAutoConfiguration 的代码如下所示:

orz,有什么东西导致了这两个配置类的优先级变得更高了吗?

经验证,可以排除以下因素:

  • @Bean

  • EnvironmentAware

所以,初步推测是 org.springframework.boot.context.properties.bind.Binder 的问题,主动绑定属性,导致提升了该配置类的优先级,同样导致 @AutoConfigureBefore 注解失效。

验证如下:

在ConfigTest中使用Binder加载配置文件中的信息,同时通过 @AutoConfigureBefore 注解设置ConfigTest2先于 ConfigTest加载。

结果,ConfigTest更先加载。

所以,问题出在 org.springframework.boot.context.properties.bind.Binder 上,只要在EncryptionPropertyConfig也使用一下org.springframework.boot.context.properties.bind.Binder,随便读取一个配置,是不是就可以使 @AutoConfigureBefore 生效了?

并不是!!!

被误导了。实测发现,如果随便使用Binder绑定一个属性,并不能导致该配置类地加载优先级提升一档。

所以可以排除:

  • @Bean

  • EnvironmentAware3

  • Binder

进一步排查发现,实际上和手动注入的bean对象有关,ApiAutoConfiguration 和 RedisAutoConfiguration 之所以能够比其他配置类的加载早一档,因为他们内部定义的需要手动注册的bean对象都实现了一个接口:BeanDefinitionRegistryPostProcessor ,如果配置类注册的bean对象实现了这个接口,会导致当前配置类的加载优先级高一个挡位。

假设数值越大优先级越高, AutoConfigureBefore 或者AutoConfigureAfter 注解对配置优先级的影响是1-100,那么配置类中注册实现BeanDefinitionRegistryPostProcessor接口的bean对象,该配置类的优先级直接+1000,所以相对于没有该类型bean对象的配置类,它们拥有更高的加载优先级,而对于同样拥有该类型bean对象的配置类,都加了1000,相对而言等同于没加,所以AutoConfigureBefore又开始生效了。

测试验证如下:

首先定义配置类ConfigTest,并设置@AutoConfigureBefore(RedisAutoConfiguration.class) :

其中BeanTest是一个实现了BeanDefinitionRegistryPostProcessor接口的bean对象:

结果符合预期,ConfigTest加载顺序先于 RedisAutoConfiguration

但实际上配置类的加载顺序非常容易受到干扰,已知出现以下情况,会出现AutoConfigureBefore失效的情况:

  • @SpringBootApplication(scanBasePackages = "com.**.*") 包扫描路径下的配置类,加载顺序由spring内部决定,无法自定义。

  • 配置类注册的bean对象实现了 BeanDefinitionRegistryPostProcessor接口,加载顺序直接提升一个档次。

  • 如果使用AutoConfigureBefore 注解定义加载顺序 A > C,B > C,spring内部决定了B>A,所以B先加载,但是B中引用了C中注册的bean对象,所以加载顺序就会变成 B > C > B > A。解释:B最先被构造,但是B中需要用到C里的对象,所以需要加载C,C加载完再加载B剩余的部分,最后加载A。 B和C的引用关系,导致了A>C的AutoConfigureBefore 注解失效。 暨,直接引用的优先级高于AutoConfigureBefore注解的优先级。

  • etc


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/993284.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号