头秃了,使用@AutoConfigureBefore调整配置顺序竟没生效?

简介: 前言如何自定义一个starter?分享一个经典的误区源码分析自动配置类如何排序?准备自己的自动配置类将自动配置类设置在spring.factories如何指定自动配置类的执行顺序?总结

前言

日常工作中对于Spring Boot 提供的一些启动器可能已经足够使用了,但是不可避免的需要自定义启动器,比如整合一个陌生的组件,也想要达到开箱即用的效果。

在上一章节从底层源码介绍了Spring Boot 的自动配置的原理,未读过的朋友建议看一下:Spring Boot 自动配置源码解析

这篇文章将会介绍如何自定义一个启动器,同时对于自动配置类的执行顺序做一个详细的分析。

如何自定义一个starter?

启动器的核心其实就是自动配置类,在自动配置源码分析的章节已经介绍过,AutoConfigurationImportSelector是从spring.factories中加载自动配置类,因此只需要将自定义的自动配置类设置在该文件中即可。

读过源码的朋友都知道自动配置类常用的一些注解,总结如下:

  1. @Configuration:该注解标志这是一个配置类,「自动配置类可以不加该注解」
  2. @EnableConfigurationProperties:这个配置也是经常使用了,使得指定的属性配置生效。一般自动配置类都需要从全局属性配置中读取自定义的配置,这就是一个开关。
  3. @ConditionalOnXxxx:该注解是自动配置类的核心了,自动配置类既要启动时自动配置,又要保证用户用户自定义的配置覆盖掉自动配置,该注解就是一个条件语句,只有当指定条件成立才会执行某操作。不理解的,请看作者前面的一篇文章:这类注解都不知道,还说用过Spring Boot~
  4. @AutoConfigureAfter:指定自动配置类的执行先后顺序,下文详细介绍。
  5. @AutoConfigureBefore:指定自动配置列的执行先后顺序,下文详细介绍。
  6. @AutoConfigureOrder:指定自动配置类的优先级,下文详细介绍。

有了以上准备,自定义一个starter非常简单,分为两个步骤。

1. 准备自己的自动配置类

启动器的灵魂核心就是自动配置类,因此需要首先创建一个自动配置类,如下:

@Configuration
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE+5)
@ConditionalOnProperty(prefix = "my.auto",name = "enabled",havingValue = "true",matchIfMissing = true)
public class MyCustomAutoConfiguration {
}

以上自动配置类只是作者简单的按照格式随手写了一个,真实开发中需要根据启动器的业务做默认配置。

2. 将自动配置类设置在spring.factories

标注了@Configuration注解的自动配置类如果不放在spring.factories文件中,仅仅是一个普通的配置类而已。想要其成为自动配置类,需要在spring.factories文件中设置,如下:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.autoconfig.MyCustomAutoConfiguration

经过以上的配置,粗略的启动器完成了,只需要打包,然后Maven引入即可工作。

如何指定自动配置类的执行顺序?

自动配置类需要定义执行顺序吗?答案:肯定的。比如Mybatis的自动配置类,肯定要在数据源的自动配置类之后执行,否则如何创建SqlSessionFactory

如何自定义自动配置类的执行顺序呢?此时就需要用到上文提到的三个注解,如下:

  1. @AutoConfigureAfter:当前配置类在指定配置类之后执行
  2. @AutoConfigureBefore:当前配置类在指定配置类之前执行
  3. @AutoConfigureOrder:指定优先级,数值越小,优先级越高。

分享一个经典的误区

对于Spring Boot不是很了解的人写出的代码真是「不堪入目」,曾经看过有人在「普通的配置类」上使用@AutoConfigurexxx注解,如下;

@Configuration
@AutoConfigureBefore(Config2.class)
public class Config1{}
@Configuration
public class Config2{}

是不是感觉很爽,原来还能这么指定配置类的执行顺序.....(此处省略一万字)

可能有时候走了狗屎运给你一种错觉还真的配置成功了。实际上这种方式是不可行的,以上三个注解只有针对自动配置类才会生效。

源码分析自动配置类如何排序?

其实关键的代码还是在AutoConfigurationImportSelector中,将自动配置类从spring.factories加载出来之后会根据条件排序,在selectImports()方法中最后一行代码如下:

return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
     .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
     .collect(Collectors.toList());

上面的代码则是将排序好的自动配置类返回,跟进代码,发现最终的实现都在AutoConfigurationSorter.getInPriorityOrder()方法中,逻辑如下图:

具体的流程如上图,排序也是按照先后顺序,如下:

  1. 先按照字母排序
  2. 按照@AutoConfigureOrder优先级排序
  3. 最终按照@AutoConfigureAfter@AutoConfigureBefore排序

从上面配置的顺序可以知道,最终决定权还是在@AutoConfigureAfter@AutoConfigureBefore这两个注解。

总结

本文介绍了如何自定义一个启动器以及指定自动配置类的执行顺序,通过作者的介绍,希望读者们能够理解并灵活运用。

相关文章
|
Kubernetes Cloud Native Java
Activiti 简介以及最新activiti依赖 pom.xml文件(使用时注意对应版本号)
Activiti 简介以及最新activiti依赖 pom.xml文件(使用时注意对应版本号)
963 2
|
监控 druid Java
Spring Boot 3 集成 Druid 连接池详解
在现代的Java应用中,使用一个高效可靠的数据源是至关重要的。Druid连接池作为一款强大的数据库连接池,提供了丰富的监控和管理功能,成为很多Java项目的首选。本文将详细介绍如何在Spring Boot 3项目中配置数据源,集成Druid连接池,以实现更高效的数据库连接管理。
11950 2
Spring Boot 3 集成 Druid 连接池详解
|
消息中间件 存储 负载均衡
2024消息队列“四大天王”:Rabbit、Rocket、Kafka、Pulsar巅峰对决
本文对比了 RabbitMQ、RocketMQ、Kafka 和 Pulsar 四种消息队列系统,涵盖架构、性能、可用性和适用场景。RabbitMQ 以灵活路由和可靠性著称;RocketMQ 支持高可用和顺序消息;Kafka 专为高吞吐量和低延迟设计;Pulsar 提供多租户支持和高可扩展性。性能方面,吞吐量从高到低依次为
5420 1
|
存储 监控 Java
OpenFeign请求拦截器组件RequestInterceptor原理与使用场景
该文章讲述了OpenFeign中的请求拦截器组件RequestInterceptor的原理及其常见使用场景。
OpenFeign请求拦截器组件RequestInterceptor原理与使用场景
|
存储 关系型数据库 MySQL
MySQL基础命令及使用示例
这些基础命令构成了与MySQL数据库交互的核心,理解并掌握它们对于进行有效的数据库操作至关重要。在实际使用中,建议结合实际案例和需求来练习这些命令,以加深理解和提高效率。
359 3
|
Java Spring
AutoConfigureBefore不生效
AutoConfigureBefore不生效
541 0
|
Java Spring 容器
SpringBoot自动装配原理之@Import注解解析
SpringBoot自动装配原理之@Import注解解析
476 0
|
存储 开发工具 数据安全/隐私保护
版本控制:让你的代码有迹可循
版本控制:让你的代码有迹可循
|
SQL Java 数据库连接
myabtis中是否可以映射 Enum 枚举类
myabtis中是否可以映射 Enum 枚举类