Browse Source

Fix gh 619 pass customisers in bean post processors (#627)

* Switch to passing customisers in BeanPostProcessor instead of the
SmartInitializingSingleton.

* Do not instantiate ReactorLoadBalancerExchangeFilterFunction while registering
LB BeanPostProcessor.

* Do not instantiate ReactorLoadBalancerExchangeFilterFunction while registering
LB BeanPostProcessor.

* Extract BeanPostProcessor instantiation to a separate configuration.

* Fix tests.

* Switch to using generics for DeferringLoadBalancerExchangeFilterFunction
and reusing BPP configuration for Ribbon. Add more test assertions.

* Add javadocs.

* Add test verifying LB filters added when WebClient built in constructor.
pull/643/head
Olga Maciaszek-Sharma 5 years ago committed by GitHub
parent
commit
b1b0ec86a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 70
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/DeferringLoadBalancerExchangeFilterFunction.java
  2. 109
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/LoadBalancerBeanPostProcessorAutoConfiguration.java
  3. 58
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/LoadBalancerWebClientBuilderBeanPostProcessor.java
  4. 32
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/ReactiveLoadBalancerAutoConfiguration.java
  5. 37
      spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerClientAutoConfiguration.java
  6. 1
      spring-cloud-commons/src/main/resources/META-INF/spring.factories
  7. 22
      spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/LoadBalancerTestUtils.java
  8. 44
      spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactiveLoadBalancerAutoConfigurationTests.java
  9. 38
      spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerClientAutoConfigurationTests.java
  10. 2
      spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/LoadBalancerAutoConfiguration.java

70
spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/DeferringLoadBalancerExchangeFilterFunction.java

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.client.loadbalancer.reactive;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeFunction;
/**
* An {@link ExchangeFilterFunction} implementation that uses {@link ObjectProvider} to
* resolve appropriate load-balancing {@link ExchangeFilterFunction} delegate when the
* {@link ExchangeFilterFunction#filter(ClientRequest, ExchangeFunction)} method is first
* called.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.0
*/
public class DeferringLoadBalancerExchangeFilterFunction<T extends ExchangeFilterFunction>
implements ExchangeFilterFunction {
private final ObjectProvider<T> exchangeFilterFunctionProvider;
private T delegate;
public DeferringLoadBalancerExchangeFilterFunction(
ObjectProvider<T> exchangeFilterFunctionProvider) {
this.exchangeFilterFunctionProvider = exchangeFilterFunctionProvider;
}
@Override
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
tryResolveDelegate();
return delegate.filter(request, next);
}
// Visible for tests
void tryResolveDelegate() {
if (delegate == null) {
delegate = exchangeFilterFunctionProvider.getIfAvailable();
if (delegate == null) {
throw new IllegalStateException(
"ReactorLoadBalancerExchangeFilterFunction not available.");
}
}
}
// Visible for tests
T getDelegate() {
return delegate;
}
}

109
spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/LoadBalancerBeanPostProcessorAutoConfiguration.java

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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.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.condition.ConditionalOnMissingBean;
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
@ConditionalOnClass(WebClient.class)
@Conditional(LoadBalancerBeanPostProcessorAutoConfiguration.OnAnyLoadBalancerImplementationPresentCondition.class)
public class LoadBalancerBeanPostProcessorAutoConfiguration {
@Bean
public LoadBalancerWebClientBuilderBeanPostProcessor loadBalancerWebClientBuilderBeanPostProcessor(
DeferringLoadBalancerExchangeFilterFunction deferringExchangeFilterFunction,
ApplicationContext context) {
return new LoadBalancerWebClientBuilderBeanPostProcessor(
deferringExchangeFilterFunction, context);
}
@Configuration
@Conditional(ReactorLoadBalancerClientAutoConfiguration.OnNoRibbonDefaultCondition.class)
@ConditionalOnBean(ReactiveLoadBalancer.Factory.class)
protected static class ReactorDeferringLoadBalancerFilterConfig {
@Bean
@Primary
DeferringLoadBalancerExchangeFilterFunction<ReactorLoadBalancerExchangeFilterFunction> reactorDeferringLoadBalancerExchangeFilterFunction(
ObjectProvider<ReactorLoadBalancerExchangeFilterFunction> exchangeFilterFunctionProvider) {
return new DeferringLoadBalancerExchangeFilterFunction<>(
exchangeFilterFunctionProvider);
}
}
@Configuration
@ConditionalOnBean(LoadBalancerClient.class)
@AutoConfigureAfter(ReactorDeferringLoadBalancerFilterConfig.class)
@Deprecated
protected static class ReactiveLoadBalancerConfig {
@Bean
@ConditionalOnMissingBean
DeferringLoadBalancerExchangeFilterFunction<LoadBalancerExchangeFilterFunction> deferringLoadBalancerExchangeFilterFunction(
ObjectProvider<LoadBalancerExchangeFilterFunction> 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 {
}
}
}

58
spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/LoadBalancerWebClientBuilderBeanPostProcessor.java

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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;
}
}

32
spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/ReactiveLoadBalancerAutoConfiguration.java

@ -16,16 +16,10 @@ @@ -16,16 +16,10 @@
package org.springframework.cloud.client.loadbalancer.reactive;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -44,32 +38,6 @@ import org.springframework.web.reactive.function.client.WebClient; @@ -44,32 +38,6 @@ import org.springframework.web.reactive.function.client.WebClient;
@Deprecated
public class ReactiveLoadBalancerAutoConfiguration {
@LoadBalanced
@Autowired(required = false)
private List<WebClient.Builder> webClientBuilders = Collections.emptyList();
public List<WebClient.Builder> getBuilders() {
return this.webClientBuilders;
}
@Bean
public SmartInitializingSingleton loadBalancedWebClientInitializer(
final List<WebClientCustomizer> customizers) {
return () -> {
for (WebClient.Builder webClientBuilder : getBuilders()) {
for (WebClientCustomizer customizer : customizers) {
customizer.customize(webClientBuilder);
}
}
};
}
@Bean
public WebClientCustomizer loadBalancerClientWebClientCustomizer(
LoadBalancerExchangeFilterFunction filterFunction) {
return builder -> builder.filter(filterFunction);
}
@Bean
public LoadBalancerExchangeFilterFunction loadBalancerExchangeFilterFunction(
LoadBalancerClient client) {

37
spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerClientAutoConfiguration.java

@ -16,16 +16,11 @@ @@ -16,16 +16,11 @@
package org.springframework.cloud.client.loadbalancer.reactive;
import java.util.Collections;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
@ -63,45 +58,15 @@ public class ReactorLoadBalancerClientAutoConfiguration { @@ -63,45 +58,15 @@ public class ReactorLoadBalancerClientAutoConfiguration {
@Conditional(OnNoRibbonDefaultCondition.class)
protected static class ReactorLoadBalancerExchangeFilterFunctionConfig {
private List<WebClient.Builder> webClientBuilders = Collections.emptyList();
List<WebClient.Builder> getBuilders() {
return this.webClientBuilders;
}
@Bean
public SmartInitializingSingleton loadBalancedWebClientInitializer(
final List<WebClientCustomizer> customizers) {
return () -> {
for (WebClient.Builder webClientBuilder : getBuilders()) {
for (WebClientCustomizer customizer : customizers) {
customizer.customize(webClientBuilder);
}
}
};
}
@Bean
public WebClientCustomizer loadBalancerClientWebClientCustomizer(
ReactorLoadBalancerExchangeFilterFunction filterFunction) {
return builder -> builder.filter(filterFunction);
}
@Bean
public ReactorLoadBalancerExchangeFilterFunction loadBalancerExchangeFilterFunction(
ReactiveLoadBalancer.Factory loadBalancerFactory) {
return new ReactorLoadBalancerExchangeFilterFunction(loadBalancerFactory);
}
@LoadBalanced
@Autowired(required = false)
void setWebClientBuilders(List<WebClient.Builder> webClientBuilders) {
this.webClientBuilders = webClientBuilders;
}
}
private static final class OnNoRibbonDefaultCondition extends AnyNestedCondition {
static final class OnNoRibbonDefaultCondition extends AnyNestedCondition {
private OnNoRibbonDefaultCondition() {
super(ConfigurationPhase.REGISTER_BEAN);

1
spring-cloud-commons/src/main/resources/META-INF/spring.factories

@ -10,6 +10,7 @@ org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscove @@ -10,6 +10,7 @@ org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscove
org.springframework.cloud.client.hypermedia.CloudHypermediaAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\

22
spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/LoadBalancerTestUtils.java

@ -18,6 +18,8 @@ package org.springframework.cloud.client.loadbalancer.reactive; @@ -18,6 +18,8 @@ package org.springframework.cloud.client.loadbalancer.reactive;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
@ -39,9 +41,10 @@ final class LoadBalancerTestUtils { @@ -39,9 +41,10 @@ final class LoadBalancerTestUtils {
throw new IllegalStateException("Can't instantiate a utility class");
}
static ConfigurableApplicationContext init(Class<?> config, Class<?> clientClass) {
static ConfigurableApplicationContext init(Class<?>... configClasses) {
return new SpringApplicationBuilder().web(WebApplicationType.NONE)
.sources(config, WebClientAutoConfiguration.class, clientClass).run();
.sources(ArrayUtils.add(configClasses, WebClientAutoConfiguration.class))
.run();
}
@SuppressWarnings("unchecked")
@ -54,8 +57,19 @@ final class LoadBalancerTestUtils { @@ -54,8 +57,19 @@ final class LoadBalancerTestUtils {
Class<?> exchangeFilterFunctionClass) {
List<ExchangeFilterFunction> filters = getFilters(webClientBuilder);
then(filters).hasSize(1);
ExchangeFilterFunction interceptor = filters.get(0);
then(interceptor).isInstanceOf(exchangeFilterFunctionClass);
then(filters.get(0))
.isInstanceOf(DeferringLoadBalancerExchangeFilterFunction.class);
DeferringLoadBalancerExchangeFilterFunction interceptor = (DeferringLoadBalancerExchangeFilterFunction) filters
.get(0);
interceptor.tryResolveDelegate();
then(interceptor.getDelegate()).isInstanceOf(exchangeFilterFunctionClass);
}
static void assertLoadBalanced(WebClient webClient,
Class<?> exchangeFilterFunctionClass) {
assertLoadBalanced(
(WebClient.Builder) ReflectionTestUtils.getField(webClient, "builder"),
exchangeFilterFunctionClass);
}
}

44
spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactiveLoadBalancerAutoConfigurationTests.java

@ -23,6 +23,7 @@ import java.util.Random; @@ -23,6 +23,7 @@ import java.util.Random;
import org.junit.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
@ -36,7 +37,9 @@ import org.springframework.context.annotation.Configuration; @@ -36,7 +37,9 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerTestUtils.assertLoadBalanced;
import static org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerTestUtils.getFilters;
/**
@ -56,7 +59,15 @@ public class ReactiveLoadBalancerAutoConfigurationTests { @@ -56,7 +59,15 @@ public class ReactiveLoadBalancerAutoConfigurationTests {
WebClient.Builder webClientBuilder = webClientBuilders.values().iterator().next();
then(webClientBuilder).isNotNull();
assertLoadBalanced(webClientBuilder);
assertLoadBalanced(webClientBuilder, LoadBalancerExchangeFilterFunction.class);
final Map<String, OneWebClientBuilder.TestService> testServiceMap = context
.getBeansOfType(OneWebClientBuilder.TestService.class);
then(testServiceMap).isNotNull().hasSize(1);
OneWebClientBuilder.TestService testService = testServiceMap.values().stream()
.findFirst().get();
assertLoadBalanced(testService.webClient,
LoadBalancerExchangeFilterFunction.class);
}
@Test
@ -70,7 +81,7 @@ public class ReactiveLoadBalancerAutoConfigurationTests { @@ -70,7 +81,7 @@ public class ReactiveLoadBalancerAutoConfigurationTests {
TwoWebClientBuilders.Two two = context.getBean(TwoWebClientBuilders.Two.class);
then(two.loadBalanced).isNotNull();
assertLoadBalanced(two.loadBalanced);
assertLoadBalanced(two.loadBalanced, LoadBalancerExchangeFilterFunction.class);
then(two.nonLoadBalanced).isNotNull();
then(getFilters(two.nonLoadBalanced)).isNullOrEmpty();
@ -99,20 +110,20 @@ public class ReactiveLoadBalancerAutoConfigurationTests { @@ -99,20 +110,20 @@ public class ReactiveLoadBalancerAutoConfigurationTests {
then(webClientBuilders).hasSize(1);
assertThatThrownBy(
() -> context.getBean(LoadBalancerExchangeFilterFunction.class))
.isInstanceOf(NoSuchBeanDefinitionException.class);
WebClient.Builder builder = context.getBean(WebClient.Builder.class);
then(builder).isNotNull();
then(getFilters(builder)).isNullOrEmpty();
assertLoadBalanced(builder, ReactorLoadBalancerExchangeFilterFunction.class);
}
private ConfigurableApplicationContext init(Class<?> config) {
return LoadBalancerTestUtils.init(config,
ReactiveLoadBalancerAutoConfiguration.class);
}
private void assertLoadBalanced(WebClient.Builder builder) {
LoadBalancerTestUtils.assertLoadBalanced(builder,
LoadBalancerExchangeFilterFunction.class);
ReactiveLoadBalancerAutoConfiguration.class,
LoadBalancerBeanPostProcessorAutoConfiguration.class);
}
@Configuration
@ -156,6 +167,21 @@ public class ReactiveLoadBalancerAutoConfigurationTests { @@ -156,6 +167,21 @@ public class ReactiveLoadBalancerAutoConfigurationTests {
return WebClient.builder();
}
@Bean
TestService testService() {
return new TestService(loadBalancedWebClientBuilder());
}
private final class TestService {
public final WebClient webClient;
private TestService(WebClient.Builder builder) {
this.webClient = builder.build();
}
}
}
@Configuration

38
spring-cloud-commons/src/test/java/org/springframework/cloud/client/loadbalancer/reactive/ReactorLoadBalancerClientAutoConfigurationTests.java

@ -31,6 +31,7 @@ import org.springframework.context.annotation.Primary; @@ -31,6 +31,7 @@ import org.springframework.context.annotation.Primary;
import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerTestUtils.assertLoadBalanced;
import static org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerTestUtils.getFilters;
/**
@ -50,7 +51,16 @@ public class ReactorLoadBalancerClientAutoConfigurationTests { @@ -50,7 +51,16 @@ public class ReactorLoadBalancerClientAutoConfigurationTests {
WebClient.Builder webClientBuilder = webClientBuilders.values().iterator().next();
then(webClientBuilder).isNotNull();
assertLoadBalanced(webClientBuilder);
assertLoadBalanced(webClientBuilder,
ReactorLoadBalancerExchangeFilterFunction.class);
final Map<String, OneWebClientBuilder.TestService> testServiceMap = context
.getBeansOfType(OneWebClientBuilder.TestService.class);
then(testServiceMap).isNotNull().hasSize(1);
OneWebClientBuilder.TestService testService = testServiceMap.values().stream()
.findFirst().get();
assertLoadBalanced(testService.webClient,
ReactorLoadBalancerExchangeFilterFunction.class);
}
@Test
@ -64,7 +74,8 @@ public class ReactorLoadBalancerClientAutoConfigurationTests { @@ -64,7 +74,8 @@ public class ReactorLoadBalancerClientAutoConfigurationTests {
TwoWebClientBuilders.Two two = context.getBean(TwoWebClientBuilders.Two.class);
then(two.loadBalanced).isNotNull();
assertLoadBalanced(two.loadBalanced);
assertLoadBalanced(two.loadBalanced,
ReactorLoadBalancerExchangeFilterFunction.class);
then(two.nonLoadBalanced).isNotNull();
then(getFilters(two.nonLoadBalanced)).isNullOrEmpty();
@ -86,12 +97,8 @@ public class ReactorLoadBalancerClientAutoConfigurationTests { @@ -86,12 +97,8 @@ public class ReactorLoadBalancerClientAutoConfigurationTests {
private ConfigurableApplicationContext init(Class<?> config) {
return LoadBalancerTestUtils.init(config,
ReactorLoadBalancerClientAutoConfiguration.class);
}
private void assertLoadBalanced(WebClient.Builder webClientBuilder) {
LoadBalancerTestUtils.assertLoadBalanced(webClientBuilder,
ReactorLoadBalancerExchangeFilterFunction.class);
ReactorLoadBalancerClientAutoConfiguration.class,
LoadBalancerBeanPostProcessorAutoConfiguration.class);
}
@Configuration
@ -119,6 +126,21 @@ public class ReactorLoadBalancerClientAutoConfigurationTests { @@ -119,6 +126,21 @@ public class ReactorLoadBalancerClientAutoConfigurationTests {
return WebClient.builder();
}
@Bean
TestService testService() {
return new TestService(loadBalancedWebClientBuilder());
}
private final class TestService {
public final WebClient webClient;
private TestService(WebClient.Builder builder) {
this.webClient = builder.build();
}
}
}
@Configuration

2
spring-cloud-loadbalancer/src/main/java/org/springframework/cloud/loadbalancer/config/LoadBalancerAutoConfiguration.java

@ -21,6 +21,7 @@ import java.util.List; @@ -21,6 +21,7 @@ import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration;
import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancerAutoConfiguration;
import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClientSpecification;
@ -36,6 +37,7 @@ import org.springframework.context.annotation.Configuration; @@ -36,6 +37,7 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@LoadBalancerClients
@AutoConfigureBefore({ ReactorLoadBalancerClientAutoConfiguration.class,
LoadBalancerBeanPostProcessorAutoConfiguration.class,
ReactiveLoadBalancerAutoConfiguration.class })
public class LoadBalancerAutoConfiguration {

Loading…
Cancel
Save