Closed c-hui closed 4 months ago
I also encountered the same problem, I used the webflux framework and turned on loadbalancer.
springcloud2023.0.0 spring-cloud-commons4.1.1 springboot(spring-boot-starter-webflux)3.2.3
trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration' of type [org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). The currently created BeanPostProcessor [loadBalancerWebClientBuilderBeanPostProcessor] is declared through a non-static factory method on that class; consider declaring it as static instead.
trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration$ReactorDeferringLoadBalancerFilterConfig' of type [org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration$ReactorDeferringLoadBalancerFilterConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [loadBalancerWebClientBuilderBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
trationDelegate$BeanPostProcessorChecker : Bean 'reactorDeferringLoadBalancerExchangeFilterFunction' of type [org.springframework.cloud.client.loadbalancer.reactive.DeferringLoadBalancerExchangeFilterFunction] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [loadBalancerWebClientBuilderBeanPostProcessor]? Check the corresponding BeanPostProcessor declaration and its dependencies.
After tracking down, I found that the initialization order of these two classes was not as expected. In fact, 'LoadBalancerBeanPostProcessorAutoConfiguration' was initialized before 'LoadBalancerAutoConfiguration'.
I currently have a solution. Exclude this automation configuration 'org.springframework.cloud. Client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration', customize an automation configuration of 'WebClient. Builder', and add the processing in the 'LoadBalancerWebClientBuilderBeanPostProcessor' to the custom 'WebClient. Builder' configuration.
package org.springframework.cloud.client.loadbalancer.reactive;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.web.reactive.function.client.WebClient;
/**
* An auto-configuration that provides a {@link BeanPostProcessor} that allows the use of
* a {@link LoadBalanced} {@link WebClient.Builder} with
* {@link ReactorLoadBalancerExchangeFilterFunction} and {@link ReactiveLoadBalancer} used
* under the hood. NOTE: This has been extracted to a separate configuration in order to
* not impact instantiation and post-processing of other Reactor-LoadBalancer-related
* beans.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(WebClient.class)
@Conditional(LoadBalancerBeanPostProcessorAutoConfiguration.OnAnyLoadBalancerImplementationPresentCondition.class)
public class LoadBalancerBeanPostProcessorAutoConfiguration {
@Bean
public LoadBalancerWebClientBuilderBeanPostProcessor loadBalancerWebClientBuilderBeanPostProcessor(
DeferringLoadBalancerExchangeFilterFunction deferringExchangeFilterFunction, ApplicationContext context) {
return new LoadBalancerWebClientBuilderBeanPostProcessor(deferringExchangeFilterFunction, context);
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(ReactiveLoadBalancer.Factory.class)
protected static class ReactorDeferringLoadBalancerFilterConfig {
@Bean
@Primary
DeferringLoadBalancerExchangeFilterFunction<LoadBalancedExchangeFilterFunction> reactorDeferringLoadBalancerExchangeFilterFunction(
ObjectProvider<LoadBalancedExchangeFilterFunction> exchangeFilterFunctionProvider) {
return new DeferringLoadBalancerExchangeFilterFunction<>(exchangeFilterFunctionProvider);
}
}
static final class OnAnyLoadBalancerImplementationPresentCondition extends AnyNestedCondition {
private OnAnyLoadBalancerImplementationPresentCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnBean(ReactiveLoadBalancer.Factory.class)
static class ReactiveLoadBalancerFactoryPresent {
}
@ConditionalOnBean(LoadBalancerClient.class)
static class LoadBalancerClientPresent {
}
}
}
package org.springframework.cloud.client.loadbalancer.reactive;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.ApplicationContext;
import org.springframework.web.reactive.function.client.WebClient;
/**
* A {@link BeanPostProcessor} that applies
* {@link DeferringLoadBalancerExchangeFilterFunction} filter to all
* {@link WebClient.Builder} instances annotated with {@link LoadBalanced}.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.0
*/
public class LoadBalancerWebClientBuilderBeanPostProcessor implements BeanPostProcessor {
private final DeferringLoadBalancerExchangeFilterFunction exchangeFilterFunction;
private final ApplicationContext context;
public LoadBalancerWebClientBuilderBeanPostProcessor(
DeferringLoadBalancerExchangeFilterFunction exchangeFilterFunction, ApplicationContext context) {
this.exchangeFilterFunction = exchangeFilterFunction;
this.context = context;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebClient.Builder) {
if (context.findAnnotationOnBean(beanName, LoadBalanced.class) == null) {
return bean;
}
((WebClient.Builder) bean).filter(exchangeFilterFunction);
}
return bean;
}
}
The customized configuration of 'WebClient. Builder':
package com.conwayd.common.web.configs;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration;
import org.springframework.boot.web.reactive.function.client.WebClientCustomizer;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.reactive.DeferringLoadBalancerExchangeFilterFunction;
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancedExchangeFilterFunction;
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration;
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
import org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration;
import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.web.reactive.function.client.WebClient;
/**
* 自定义webclient
* <br>
* 修复框架中 {@link LoadBalancerBeanPostProcessorAutoConfiguration#loadBalancerWebClientBuilderBeanPostProcessor(DeferringLoadBalancerExchangeFilterFunction, ApplicationContext)} 的初始化问题
*
* @author conwayD at 2024-03-08 10:27
* @since 1.0.0
*/
@ConditionalOnClass(WebClient.class)
@Conditional(CustomizeWebClientAutoConfiguration.OnAnyLoadBalancerImplementationPresentCondition.class)
@AutoConfiguration(after = {CodecsAutoConfiguration.class, ClientHttpConnectorAutoConfiguration.class})
@AutoConfigureAfter({LoadBalancerAutoConfiguration.class, BlockingLoadBalancerClientAutoConfiguration.class})
public class CustomizeWebClientAutoConfiguration {
@Bean
@Primary
@Scope("prototype")
public WebClient.Builder webClientBuilder(ObjectProvider<WebClientCustomizer> customizerProvider,
ObjectProvider<LoadBalancedExchangeFilterFunction> exchangeFilterFunctionProvider) {
WebClient.Builder builder = WebClient.builder();
customizerProvider.orderedStream().forEach((customizer) -> customizer.customize(builder));
DeferringLoadBalancerExchangeFilterFunction<LoadBalancedExchangeFilterFunction> filterFunction =
new DeferringLoadBalancerExchangeFilterFunction<>(exchangeFilterFunctionProvider);
builder.filter(filterFunction);
return builder;
}
static final class OnAnyLoadBalancerImplementationPresentCondition extends AnyNestedCondition {
private OnAnyLoadBalancerImplementationPresentCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnBean(ReactiveLoadBalancer.Factory.class)
static class ReactiveLoadBalancerFactoryPresent {
}
@ConditionalOnBean(LoadBalancerClient.class)
static class LoadBalancerClientPresent {
}
}
}
Hello @c-hui. Thanks for reporting the issue. This is a duplicate of https://github.com/spring-cloud/spring-cloud-commons/issues/1315. Please upgrade to the newest release.
Version:
description:
when startup, have warn messages :
I see it is indeed non-static here: https://github.com/spring-cloud/spring-cloud-commons/blob/v4.1.1/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/LoadBalancerBeanPostProcessorAutoConfiguration.java#L50