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

简介: 使用@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后面执行而以为生效了),希望本文能帮助到你。

相关文章
【el-tree】树形结构拖拽,拖动修改分组
【el-tree】树形结构拖拽,拖动修改分组
1290 1
|
Web App开发 JavaScript 前端开发
安卓webview访问vue工程白屏/无响应/无法加载问题处理
本文目录 1. 问题出现 2. 尝试更换内嵌浏览器 3. 尝试各种babel配置 4. 二分排除法定位问题 5. 模拟器与真机测试还不一样 6. 总结 7. 反思
3391 0
Vue2分页(Pagination)
本文介绍了如何在 Vue3 中创建一个自定义分页组件(Pagination)。该组件支持传入多个参数,如当前页数、每页条数、是否隐藏单页分页等,并提供了丰富的功能,包括快速跳转、显示数据总量及分页器位置调整。通过示例代码展示了组件的具体实现方式,包括模板结构、计算属性、监听方法及样式设置。此外,还介绍了如何在项目中引入并使用该分页组件。
537 0
Vue2分页(Pagination)
|
Oracle Java 关系型数据库
2023年震撼!Java在TIOBE排行榜滑坡至历史最低!
自2023年6月起,Java在TIOBE编程语言排行榜中跌至历史最低的第4位,与C#的差距缩小至1.2%。Java受欢迎程度下降的主要原因是Oracle在Java 8后引入付费许可模式,导致用户流失。尽管如此,Java仍是一门成熟、稳定且跨平台的语言,拥有庞大的用户群和丰富的生态系统。Oracle通过推出Java 17免费版及Java 21的新特性,努力保持其竞争力。未来,Java将继续与其他编程语言竞争并发展。
337 1
|
安全 前端开发 Java
Spring Security 自定义异常失效?从源码分析到解决方案
Spring Security 自定义异常失效?从源码分析到解决方案
|
Linux 虚拟化
成功解决:Xshell 无法连接虚拟机。如何使用Xshell连接CentOS7虚拟机(详细步骤过程)
这篇文章提供了使用Xshell连接CentOS 7虚拟机的详细步骤,包括编辑VMware的网络设置以启用桥接模式、检查个人电脑适配器虚拟网络的连接情况,以及通过Xshell新建并建立连接的过程。文章还提到了在虚拟机可以访问外网的情况下成功连接的后语,暗示了网络配置的重要性。
成功解决:Xshell 无法连接虚拟机。如何使用Xshell连接CentOS7虚拟机(详细步骤过程)
|
Java Spring
AutoConfigureBefore不生效
AutoConfigureBefore不生效
486 0
|
前端开发 数据库 JavaScript
基于Flowable的流程挂接自定义业务表单的设计与实践
文章讨论了如何在Flowable流程引擎中挂接自定义业务表单,以及相关设计和实践的步骤。文章中包含了一些前后端代码示例,如Vue组件的模板和脚本部分,这些代码用于实现与Flowable流程引擎交互的界面。例如,有一个按钮组件用于提交申请,点击后会触发applySubmit方法,该方法会与后端API进行交互,处理流程启动、查询关联流程等逻辑。
53927 11
|
传感器 算法 定位技术
【虚拟现实】一、AR与VR的基本原理
【虚拟现实】一、AR与VR的基本原理
973 3
|
Java Nacos 网络架构
SpringCloud Gateway的使用 + Nacos动态路由
SpringCloud Gateway的使用 + Nacos动态路由