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.
This commit is contained in:
committed by
GitHub
parent
c437379857
commit
b1b0ec86a6
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@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) {
|
||||
|
||||
@@ -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 {
|
||||
@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);
|
||||
|
||||
@@ -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,\
|
||||
|
||||
@@ -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 {
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
|
||||
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 {
|
||||
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
|
||||
|
||||
@@ -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 {
|
||||
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 {
|
||||
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 {
|
||||
|
||||
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 {
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
@Configuration
|
||||
@LoadBalancerClients
|
||||
@AutoConfigureBefore({ ReactorLoadBalancerClientAutoConfiguration.class,
|
||||
LoadBalancerBeanPostProcessorAutoConfiguration.class,
|
||||
ReactiveLoadBalancerAutoConfiguration.class })
|
||||
public class LoadBalancerAutoConfiguration {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user