news 2026/2/10 4:58:24

@AutoConfigureBefore 与 @AutoConfigureAfter

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
@AutoConfigureBefore 与 @AutoConfigureAfter

目录

1、介绍

1.1、设计目的

1.2、定义

1.3、作用域

1.4、设计限制

2、应用

2.1、使用场景

2.2、工作原理

2.3、实战示例

3、常见误区与最佳实践

3.1、最佳实践

3.2、常见误区

3.3、与其他顺序控制注解对比


前沿

控制 Spring Boot 自动配置顺序:

“我的自定义配置为什么没生效?明明加了@ConditionalOnBean,却还是报NoSuchBeanDefinitionException!”

如下所示:

如果你也曾被这类问题困扰,那很可能不是条件注解写错了,而是自动配置的执行顺序出了问题

在 Spring Boot 的自动装配体系中,时机决定一切。而 @AutoConfigureBefore和@AutoConfigureAfter,正是你掌控这一时机的“时间控制器”。

背景:为什么需要控制自动配置顺序?

Spring Boot 的魅力在于“约定优于配置”,其核心是自动配置(Auto-configuration)——通过 spring.factories 或 AutoConfiguration.imports声明一系列 @Configuration 类,在应用启动时按需加载。

但现实世界并非理想模型。多个自动配置类之间往往存在隐式依赖关系

  • 我的 AuditLogAutoConfiguration 需要 DataSource
  • 我的 CustomRedisTemplate 要覆盖默认实现
  • 我的 TraceInterceptor 必须在 Spring MVC 初始化之后注册

如果没有顺序控制,Spring 容器可能在 DataSource 还未创建时就尝试初始化你的 AuditService,导致启动失败。

于是,Spring Boot 提供了 @AutoConfigureBefore@AutoConfigureAfter—— 它们不是“可选项”,而是构建可靠自动配置的必备工具


1、介绍

1.1、设计目的

Spring Boot 的自动配置基于 条件装配(@Conditional),但多个自动配置类之间可能存在隐式依赖,“我的自动配置必须在 DataSourceAutoConfiguration 之后运行,因为我要注入DataSourceBean!”

如果没有顺序控制,Spring 无法保证 DataSource 已经创建,导致启动失败。

为了解决自动配置的“依赖顺序”问题,@AutoConfigureBefore 和 @AutoConfigureAfter 就是为此而生。

1.2、定义

如下所示:

注解作用
@AutoConfigureAfter当前自动配置类应在指定类之后执行
@AutoConfigureBefore当前自动配置类应在指定类之前执行

代码如下所示:

@AutoConfigureAfter({DataSourceAutoConfiguration.class, RedisAutoConfiguration.class}) @AutoConfigureBefore(WebMvcAutoConfiguration.class) public class MyCustomAutoConfiguration { // ... }

1.3、作用域

1.@AutoConfigureAfter:请在我指定的自动配置类之后执行我。

代码如下所示:

@AutoConfigureAfter(DataSourceAutoConfiguration.class) public class MyServiceAutoConfiguration { ... }

效果

确保 MyServiceAutoConfiguration 在 DataSourceAutoConfiguration之后被处理,从而能安全地注入 DataSource Bean。

2.@AutoConfigureBefore:“请在我指定的自动配置类之前执行我。

代码如下所示:

@AutoConfigureBefore(RedisAutoConfiguration.class) public class CustomRedisTemplateConfiguration { ... }

效果

确保你的 RedisTemplate 先于 Spring Boot 默认配置注册,从而通过 @Primary 或@ConditionalOnMissingBean 实现覆盖。

1.4、设计限制

仅作用于自动配置类,这两个注解只影响被 Spring Boot 自动配置机制管理的类,即:

1、在META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(Spring Boot 3.x)

2、或META-INF/spring.factories(Spring Boot 2.x)中声明的配置类

它们对普通@Configuration类无效!普通 Bean 的依赖应使用 @DependsOn。


2、应用

2.1、使用场景

场景1:依赖其他自动配置创建的 Bean

需求:自定义一个 UserService,它依赖 DataSource。

代码如下所示:

@Configuration @AutoConfigureAfter(DataSourceAutoConfiguration.class) // 必须在 DataSource 之后 public class UserServiceAutoConfiguration { @Bean @ConditionalOnBean(DataSource.class) // 确保 DataSource 存在 public UserService userService(DataSource dataSource) { return new UserService(dataSource); } }

为什么需要@AutoConfigureAfter?UserService

即使有 @ConditionalOnBean,如果 UserServiceAutoConfiguration 先于 DataSourceAutoConfiguration 执行,DataSource 还未注册,条件判断会失败,UserService 不会被创建。

场景2:覆盖或增强已有自动配置

需求:自定义 RedisTemplate,替换 Spring Boot 默认的。

代码如下所示:

@Configuration @AutoConfigureBefore(RedisAutoConfiguration.class) // 在 Redis 自动配置 *之前* 执行 public class CustomRedisTemplateConfiguration { @Bean @Primary // 覆盖默认 public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } }

为什么用@AutoConfigureBefore?

确保你的 @Primary. RedisTemplate 先注册,这样当 RedisAutoConfiguration 尝试创建自己的 RedisTemplate 时,会因 @ConditionalOnMissingBean 条件不满足而跳过。

场景3:Starter 组件间的依赖

需求:你开发了一个 my-starter,它依赖 spring-boot-starter-data-jpa。

在 my-starter 的自动配置类中:

@AutoConfigureAfter(JpaRepositoriesAutoConfiguration.class) public class MyStarterAutoConfiguration { // 使用 JpaRepository }

2.2、工作原理

Spring Boot 在启动时执行,如何排序?

如下所示:

3.1、扫描所有自动配置候选类:

从 classpath 下的 AutoConfiguration.imports 文件读取全限定类名。

Spring Boot 在启动时:扫描所有 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

3.2、构建依赖图:

解析每个类上的 @AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder。

3.3、拓扑排序:

使用 Kahn 算法进行有向无环图(DAG)排序,确保依赖顺序。

3.4、按序注册 Bean:

依次处理每个自动配置类,执行其中的 @Bean 方法。

⚠️注意:这些注解只影响自动配置类之间的顺序,不影响普通 @Configuration 类!

2.3、实战示例

目标:创建一个日志追踪 Starter,依赖 Web 自动配置

1. 自动配置类

@Configuration @AutoConfigureAfter(WebMvcAutoConfiguration.class) // 必须在 Web 配置之后 @ConditionalOnWebApplication public class TraceAutoConfiguration { @Bean public TraceInterceptor traceInterceptor() { return new TraceInterceptor(); } @Bean public TraceWebMvcConfigurer traceWebMvcConfigurer(TraceInterceptor interceptor) { return new TraceWebMvcConfigurer(interceptor); } }

2. WebMvcConfigurer 实现

public class TraceWebMvcConfigurer implements WebMvcConfigurer { private final TraceInterceptor interceptor; public TraceWebMvcConfigurer(TraceInterceptor interceptor) { this.interceptor = interceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(interceptor); } }

3. 注册到 spring.factories(Spring Boot 2.x)或 AutoConfiguration.imports(3.x)

# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports com.example.TraceAutoConfiguration

效果

  • 只有在 Web 环境下才生效
  • 确保 WebMvcConfigure 被正确注册到 Spring MVC

场景1:依赖其他自动配置创建的 Bean

需求:创建一个审计服务,依赖数据库。

@Configuration @AutoConfigureAfter(DataSourceAutoConfiguration.class) // 关键! @ConditionalOnClass(JdbcTemplate.class) @ConditionalOnBean(DataSource.class) public class AuditServiceAutoConfiguration { @Bean public AuditService auditService(DataSource dataSource) { return new AuditService(dataSource); } }

为什么必须加@AutoConfigureAfter?避免因顺序问题导致 @ConditionalOnBean 失效。

场景2:覆盖默认自动配置

需求:自定义 RedisTemplate,使用 JSON 序列化。

@Configuration @AutoConfigureBefore(RedisAutoConfiguration.class) // 在默认配置前执行 public class CustomRedisConfig { @Bean @Primary public RedisTemplate<String, Object> redisTemplate( RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; } }

效果

Spring Boot 的 RedisAutoConfiguration 会因 @ConditionalOnMissingBean(RedisTemplate.class)而跳过自身创建逻辑。

场景 3:Starter 组件间的协作

需求:开发一个 my-cache-starter,它依赖 spring-boot-starter-data-redis。

// my-cache-starter 的自动配置 @AutoConfigureAfter(RedisAutoConfiguration.class) @ConditionalOnBean(RedisConnectionFactory.class) public class MyCacheAutoConfiguration { @Bean public MyCacheService cacheService(RedisTemplate redisTemplate) { return new MyCacheService(redisTemplate); } }

优势:用户只需引入你的 Starter,无需关心底层 Redis 是否已配置。


3、常见误区与最佳实践

3.1、最佳实践

1. 组合使用多个类

@AutoConfigureAfter({ DataSourceAutoConfiguration.class, JpaRepositoriesAutoConfiguration.class })

2. 配合 @AutoConfigureOrder 做全局排序

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter(LoggingAutoConfiguration.class) public class TracingAutoConfiguration { ... }

3. 优先使用条件注解,而非强依赖顺序

// 更健壮的方式 @ConditionalOnBean(DataSource.class) @AutoConfigureAfter(DataSourceAutoConfiguration.class) // 双重保险

❌ 避免:循环依赖

// A.java @AutoConfigureAfter(B.class) // B.java @AutoConfigureAfter(A.class) // 启动失败!

3.2、常见误区

误区 1:以为能控制任意 Bean 的顺序

@AutoConfigureAfter只控制自动配置类的执行顺序,不能控制普通 Bean 的创建顺序。
普通 Bean 用 @DependsOn 或 @Order。

误区 2:过度使用,导致循环依赖

// A.java @AutoConfigureAfter(B.class) // B.java @AutoConfigureAfter(A.class) // 💥 循环依赖!

最佳实践:

  1. 优先使用@ConditionalOnBean,而非强依赖顺序
  2. 只在必要时使用(如确实需要前置 Bean)
  3. 明确指定具体类,避免模糊依赖
  4. 配合@AutoConfigureOrder做更精细控制(值越小越先执行)

3.3、与其他顺序控制注解对比

如下所示:@AutoConfigureOrder

注解作用范围适用场景
@AutoConfigureBefore/After自动配置类之间Starter 开发、定制 AutoConfig
@Order同类 Bean 排序(如 Interceptor、Filter)定义拦截器执行顺序
@DependsOn任意 Bean 依赖强制 A 在 B 之前初始化
@AutoConfigureOrder自动配置类全局排序设置基础配置(如日志)最先执行

能用条件注解决不用顺序控制;必须用时,优先选@AutoConfigureAfter。


总结

问题答案
什么时候用@AutoConfigureAfter?当你的自动配置依赖其他 AutoConfig 创建的 Bean
什么时候用@AutoConfigureBefore?当你要覆盖或拦截其他 AutoConfig 的行为
能否控制普通配置类❌ 不能,仅限自动配置类
是否必须使用否,但能避免 @ConditionalOnBean 失效

自动配置的顺序:决定了 Spring Boot 应用的“装配逻辑”。而 @AutoConfigureBefore/After,就是你手中的“装配指南针”。

合理使用它们,你的 Starter 将更加健壮、可组合、可预测。


参考文章:

1、SpringBoot之@AutoConfigureBefore、@AutoConfigureAfter、@AutoConfigureOrder注解

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/8 3:06:02

Qt----事件简述

目录1&#xff0c;事件的概念2&#xff0c;事件循环3&#xff0c;父子控件之间事件的传递处理4&#xff0c;事件过滤器1&#xff0c;事件的概念 定义&#xff1a; 事件是应用程序内部发生的事情或应用程序需要知道的外部事件的结果。 事件和信号的区别&#xff1a; 事件是由外…

作者头像 李华
网站建设 2026/2/6 21:30:12

AXI-A7.4.3 Atomic transactions attributes

一、atomic transactions are as follows: 1. AWLEN和AWSIZE指定写数据的字节数(对于AtomicCompare需包含比较值和交换值) AWLEN(突发长度)和AWSIZE(每次传输的字节数)共同决定了原子事务中写数据的总字节数。对于大多数原子事务,这指的是操作数的大小;但对于AtomicCom…

作者头像 李华
网站建设 2026/1/29 13:30:15

内存泄漏怎么定位和解决?core dump有哪些信息?

一、为什么会内存泄漏&#xff1f;常见场景&#xff1a;音频播放反复malloc缓冲区未freeMQTT断线重连时不断分配内存呢解析JSON字符串频繁申请堆空间回调注册后未注销导致上下文无法释放使用全局链表或队列但不清除节点二、如何定位内存泄漏&#xff1f;1、添加内存监控接口在T…

作者头像 李华
网站建设 2026/2/1 1:20:06

STL deque 的详细特征

STL deque 的详细特征 基本特性 #include <deque> using namespace std;deque<int> dq; // 声明一个int类型的双端队列 双端队列&#xff1a;允许在两端进行高效插入和删除动态数组&#xff1a;支持随机访问&#xff0c;可以像数组一样通过下标访问内存结构&a…

作者头像 李华
网站建设 2026/2/5 14:24:06

9.快速修改铜皮

铺铜后&#xff0c;需要进行细微调整。常规的方法使用鼠标拉扯铜皮边缘修改&#xff0c;很痛苦&#xff01;&#xff01;&#xff01;且效率非常低。技巧&#xff1a;1.选中要修改的铜皮2.如图所示&#xff1a;先选中modify&#xff0c;然后修改&#xff0c;然后重新铺铜。注意…

作者头像 李华
网站建设 2026/2/5 4:49:29

10.是否要成为全栈工程师?

1、软件工程师 嵌入式软件工程师 硬件工程师的关系一、各自的核心工作1. 软件工程师&#xff08;通常指“纯软件/应用层工程师”&#xff09;工作内容&#xff1a;负责非硬件相关的软件逻辑&#xff0c;比如&#xff1a;业务功能开发&#xff08;如APP界面、数据处理算法、网络…

作者头像 李华