使用@AutoConfigureBefore调整配置顺序竟没生效?(下)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 使用@AutoConfigureBefore调整配置顺序竟没生效?(下)

三大注解使用的正确姿势

针对以上case,要想达到预期效果,正确姿势只需要下面两步:


  1. 把A_SonConfig和B_ParentConfig挪动到Application扫描不到的包内,切记:一定且必须是扫描不到的包内
  2. 当前工程里增加配置META-INF/spring.factories,内容为(配置里Son和Parent前后顺序对结果无影响):


org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.fsx.autoconfig.A_SonConfig,com.fsx.autoconfig.B_ParentConfig


再次启动应用看看,打印输出:


我是被自动扫描的配置,初始化啦....
配置类ParentConfig构造器被执行...
配置类SonConfig构造器被执行...


完美。符合预期,Parent终于在Son之前完成了初始化,也就是说我们的@AutoConfigureBefore注解生效了。


使用细节注意事项


针对此使用姿势,虽然很正确,并不是完全没有“副作用”的,有如下细节平时也需要引起注意:


  • 若你不用@AutoConfigureBefore这个注解,单单就想依赖于spring.factories里的先后顺序的来控制实际的加载顺序,答案是不可以,控制不了
  • 例子中有个小细节:我每次都故意输出了我是被自动扫描的配置,初始化啦....这句话,可以发现被扫描进去配置实例化是在它前面(见错误示例),而通过spring.factories方式进去是在它的后面(见正确姿势)
  • 从这个小细节可以衍生得到结论:Spring Boot的自动配置均是通过spring.factories来指定的,它的优先级最低(执行时机是最晚的);通过扫描进来的一般都是你自己自定义的配置类,所以优先级是最高的,肯定在自动配置之前加载
  • 从这你应该学到:若你要指定扫描的包名,请千万不要扫描到形如org.springframework这种包名,否则“天下大乱”(当然喽为了防止这种情况出现,Spring Boot做了容错的。它有一个类专门检测这个case防止你配置错了,具体参见ComponentScanPackageCheck默认实现)
  • 请尽量不要让自动配置类既被扫描到了,又放在spring.factories配置了,否则后者会覆盖前者,很容易造成莫名其妙的错误


小总结,对于三大注解的正确使用姿势是应该是:请使用在你的自动配置里(一般是你自定义starter时使用),而不是使用在你业务工程中的@Configuration里,因为那会毫无效果。


三大注解解析时机浅析


为了更好的辅助理解,加强记忆,本文将这三大注解解析时机简要的絮叨一下,知道了它被解析的时机,自然就很好解释为何你那么写是无效的喽。


这三个注解的解析都是交给AutoConfigurationSorter来排序、处理的,做法类似于AnnotationAwareOrderComparator去解析排序@Order注解。核心代码如下:


class AutoConfigurationSorter {
  // 唯一给外部调用的方法:返回排序好的Names,因此返回的是个List嘛(ArrayList)
  List<String> getInPriorityOrder(Collection<String> classNames) {
    ...
    // 先按照自然顺序排一波
    Collections.sort(orderedClassNames);
    // 在按照@AutoConfigureBefore这三个注解排一波
    orderedClassNames = sortByAnnotation(classes, orderedClassNames);
    return orderedClassNames;
  }
  ...
}

此排序器被两个地方使用到:


  • AutoConfigurationImportSelector:Spring自动配置处理器,用于加载所有的自动配置类。它实现了DeferredImportSelector接口:这也顺便解释了为何自动配置是最后执行的原因~
  • AutoConfigurations:表示自动配置@Configuration类。


这个排序的“解析/排序”过程还是比较复杂的,本文点到为止,观其大意即可。你可以简单粗暴的记住结论:@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder这三个注解只能作用于自动配置类,而不能是自定义的@Configuration配置类。


总结


关于Spring Boot自动配置顺序相关的三大注解@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder就先介绍到这了,本文主要用意是为了帮助大家规范此些“常用注解”的使用,规避一些误区,端正使用姿势,避免犯错时又丈二和尚。


我看到不少文章、生产上的代码都使用错了(估计有没有效果自己的都不知道,又或者刚好歪打正着确实是在xxx后面执行而以为生效了),希望本文能帮助到你。

相关文章
|
监控 Java 索引
ES 生产中10个常见参数阈值(默认最大值)操作及优化解决方案
ES 生产中10个常见参数阈值(默认最大值)操作及优化解决方案
ES 生产中10个常见参数阈值(默认最大值)操作及优化解决方案
|
3月前
|
数据处理
重复值的判断标准是否可以根据具体业务需求进行调整?
重复值的判断标准需要紧密结合具体的业务需求进行灵活调整,这样才能确保数据处理的准确性和有效性,为业务决策提供可靠的数据支持。
128 58
|
8月前
spark3总结——分区数对带有初始值聚合操作的影响
spark3总结——分区数对带有初始值聚合操作的影响
43 4
|
消息中间件 缓存 资源调度
动态调整线程池参数实践
动态调整线程池参数实践
1288 0
|
机器学习/深度学习
|
Java 数据库连接 Maven
头秃了,使用@AutoConfigureBefore调整配置顺序竟没生效?
前言 如何自定义一个starter? 分享一个经典的误区 源码分析自动配置类如何排序? 准备自己的自动配置类 将自动配置类设置在spring.factories 如何指定自动配置类的执行顺序? 总结
|
算法 前端开发 程序员
调整数组元素顺序
调整数组元素顺序
调整数组元素顺序
|
Java 程序员 应用服务中间件
使用@AutoConfigureBefore调整配置顺序竟没生效?(上)
使用@AutoConfigureBefore调整配置顺序竟没生效?(上)
使用@AutoConfigureBefore调整配置顺序竟没生效?(上)
使用@AutoConfigureBefore调整配置顺序竟没生效?(中)
使用@AutoConfigureBefore调整配置顺序竟没生效?(中)
|
算法
顺序不能改变的算子,是否跟时间有关
顺序不能改变的算子,是否跟时间有关
106 0