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

相关文章
|
JSON Java 数据格式
微服务框架(十三)Spring Boot Logstash日志采集
  本文为Spring Boot中Log4j2对接Logstash,进行日志采集。Logstah只支持log4j,使用log4j2时需要通过TCP插件调用 此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。
|
SQL 存储 运维
Flyway基本介绍及基本使用
使用5W1H方式介绍一下在Java项目开发中使用Flyway来管理数据库版本。。
10210 0
Flyway基本介绍及基本使用
|
缓存 Linux 开发工具
CentOS 7- 配置阿里镜像源
阿里镜像官方地址http://mirrors.aliyun.com/ 1、点击官方提供的相应系统的帮助 :2、查看不同版本的系统操作: 下载源1、安装wget yum install -y wget2、下载CentOS 7的repo文件wget -O /etc/yum.
258333 0
|
安全 前端开发 Java
Spring Security 自定义异常失效?从源码分析到解决方案
Spring Security 自定义异常失效?从源码分析到解决方案
|
Java Spring
AutoConfigureBefore不生效
AutoConfigureBefore不生效
368 0
|
数据处理 Apache 流计算
实时计算引擎 Flink:从入门到深入理解
本篇详细介绍了Apache Flink实时计算引擎的基本概念和核心功能。从入门到深入,逐步介绍了Flink的数据源与接收、数据转换与计算、窗口操作以及状态管理等方面的内容,并附带代码示例进行实际操作演示。通过阅读本文,读者可以建立起对Flink实时计算引擎的全面理解,为实际项目中的实时数据处理提供了有力的指导和实践基础。
5055 2
|
存储 Java 应用服务中间件
Java规则引擎Drools急速入门
Java规则引擎Drools急速入门
Java规则引擎Drools急速入门
|
消息中间件 存储 缓存
一文快速掌握高性能内存队列Disruptor
`Disruptor`是LMAX公司开源的高性能内存消息队列,单线程处理能力可达600w订单/秒。本文从使用和设计角度探讨这款Java消息队列。作者sharkChili是Java开发者,CSDN博客专家,Java Guide项目维护者。文章介绍了Disruptor的基础使用,包括前置步骤、消息模型、消息处理器配置、生产者实现,并展示了效果。同时,文章详细解析了Disruptor的工作流程和高效原因,如无锁操作、分支预测和缓存填充。最后,作者提供相关资源链接并邀请读者加入交流群。
2834 0
|
安全 Java 开发者
Spring Security自定义认证异常和授权异常
Spring Security自定义认证异常和授权异常
1304 4