You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中WebClient.Builder添加@LoadBalanced引发循环依赖问题

Spring Boot 3.0.5中WebClient.Builder负载均衡与链路追踪的循环依赖问题

项目背景

  • 基于Spring Boot 3.0.5的微服务架构,采用注册中心管理服务,通过Zipkin实现分布式追踪
  • 引入的核心依赖:
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
    <groupId>io.zipkin.reporter2</groupId>
    <artifactId>zipkin-reporter-brave</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
    <scope>runtime</scope>
</dependency>

根据官方文档说明:

If you create the WebClient or the RestTemplate without using the auto-configured builders, automatic trace propagation won’t work!

因此必须使用自动配置的WebClient.Builder才能实现链路追踪的自动传播。但自动配置的WebClient.Builder(来自WebClientAutoConfiguration.class)并未带有@LoadBalanced注解,源码如下:

@Bean
@Scope("prototype")
@ConditionalOnMissingBean
public WebClient.Builder webClientBuilder(ObjectProvider<WebClientCustomizer> customizerProvider) {
    WebClient.Builder builder = WebClient.builder();
    customizerProvider.orderedStream().forEach((customizer) -> {
        customizer.customize(builder);
    });
    return builder;
}

为了给WebClient添加负载均衡能力,我自定义了如下Bean:

@Bean
@LoadBalanced
public WebClient.Builder webClient(WebClient.Builder builder) {
    return builder;
}

但这引发了循环依赖问题:

The dependencies of some of the beans in the application context form a cycle:

    ┌─────┐ |  webClient defined in class path resource [...//WebClientConfig.class] 
    └─────┘

我可以通过为WebClient/WebClient.Builder编写包装类来解决,但这种方式过于繁琐(因为包含大量方法)。请问该循环依赖问题的原因是什么?如何合理解决?


循环依赖原因

当你自定义@Bean @LoadBalanced WebClient.Builder时,Spring会尝试注入WebClient.Builder作为参数。但自动配置的webClientBuilder Bean带有@ConditionalOnMissingBean注解——Spring发现已经存在一个WebClient.Builder类型的Bean(就是你自定义的这个),所以不会创建自动配置的实例。这就导致你的自定义Bean需要依赖自身,形成了循环依赖。

合理解决方法

方法1:通过@Autowired列表绑定自动配置Builder并添加负载均衡(推荐)

不需要重新定义WebClient.Builder Bean,而是利用Spring的自动配置机制,给自动生成的Builder加上负载均衡标识:

@Configuration
public class WebClientConfig {

    @LoadBalanced
    @Autowired
    private List<WebClient.Builder> webClientBuilders;

    // 按需创建带负载均衡的WebClient实例
    @Bean
    public WebClient myLoadBalancedWebClient() {
        return webClientBuilders.get(0)
                // 可添加自定义配置,比如默认header、超时时间等
                .build();
    }
}

这种方式既保留了链路追踪的自动配置(自动应用WebClientCustomizer),又给Builder赋予了负载均衡能力,是最简洁的方案。

方法2:手动整合负载均衡与链路追踪自定义器

如果需要完全自定义Builder,可以手动注入负载均衡过滤器和所有自动配置的WebClientCustomizer,直接构建符合要求的Builder:

@Configuration
public class WebClientConfig {

    @Bean
    @LoadBalanced
    public WebClient.Builder loadBalancedWebClientBuilder(
            LoadBalancerExchangeFilterFunction loadBalancerFilter,
            ObjectProvider<WebClientCustomizer> customizers) {
        WebClient.Builder builder = WebClient.builder()
                .filter(loadBalancerFilter);
        // 应用所有自动配置的自定义器(包括链路追踪的)
        customizers.orderedStream().forEach(builder::customize);
        return builder;
    }
}

这种方式主动整合了负载均衡和链路追踪的能力,避免了循环依赖,同时保留了自动配置的所有特性。

方法3:用@Qualifier指定注入自动配置的Builder

如果坚持要保持原有的自定义Bean形式,可以通过@Qualifier明确指定注入自动配置的webClientBuilder实例(自动配置的Bean名称为webClientBuilder):

@Configuration
public class WebClientConfig {

    @Bean
    @LoadBalanced
    public WebClient.Builder webClient(@Qualifier("webClientBuilder") WebClient.Builder builder) {
        return builder;
    }
}

这种方式打破了循环依赖,让Spring明确知道要注入的是自动配置的Builder,而非自定义的Bean。


内容的提问来源于stack exchange,提问作者Darlyn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 05:25:10