@AutoConfigureBefore注解的失效分析

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

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

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

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

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

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

ApiAutoConfigurationRedisAutoConfiguration 的代码如下所示:

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对象有关,ApiAutoConfigurationRedisAutoConfiguration 之所以能够比其他配置类的加载早一档,因为他们内部定义的需要手动注册的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


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值