From 35ba7bab952c6b5d5c9e8dfd4829d01611baaa15 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Thu, 17 Mar 2016 11:29:46 +0000 Subject: [PATCH] Ensure that BPP dependencies are not created too early The FeignBeanPostProcessor was causing other things to misbehave by forcing early instantiation of all its dependencies. One of those is a @MessageEndpoint when Sleuth Stream is in use, and the annotation wasn't being processed because the bean was processed too early. --- .../autoconfig/TraceAutoConfiguration.java | 2 +- .../client/feign/FeignBeanPostProcessor.java | 21 +++++--- .../TraceFeignClientAutoConfiguration.java | 54 +++++++++++-------- .../log/SleuthLogAutoConfiguration.java | 4 +- .../stream/SleuthStreamAutoConfiguration.java | 2 +- 5 files changed, 51 insertions(+), 32 deletions(-) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java index 8b1d08d2e..bb4967dcf 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java @@ -61,7 +61,7 @@ public class TraceAutoConfiguration { @Bean @ConditionalOnMissingBean(Tracer.class) - public DefaultTracer traceManager(Sampler sampler, Random random, + public DefaultTracer sleuthTracer(Sampler sampler, Random random, SpanNamer spanNamer, SpanLogger spanLogger, SpanReporter spanReporter) { return new DefaultTracer(sampler, random, spanNamer, spanLogger, diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignBeanPostProcessor.java index 1becb3f52..588b30326 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/FeignBeanPostProcessor.java @@ -17,6 +17,7 @@ package org.springframework.cloud.sleuth.instrument.web.client.feign; import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.cloud.sleuth.Tracer; @@ -34,25 +35,33 @@ import feign.codec.Decoder; */ final class FeignBeanPostProcessor implements BeanPostProcessor { - private final Tracer tracer; + private Tracer tracer; + private final BeanFactory beanFactory; - FeignBeanPostProcessor(Tracer tracer) { - this.tracer = tracer; + FeignBeanPostProcessor(BeanFactory beanFactory) { + this.beanFactory = beanFactory; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof Decoder && !(bean instanceof TraceFeignDecoder)) { - return new TraceFeignDecoder(this.tracer, (Decoder) bean); + return new TraceFeignDecoder(getTracer(), (Decoder) bean); } else if (bean instanceof Retryer && !(bean instanceof TraceFeignRetryer)) { - return new TraceFeignRetryer(this.tracer, (Retryer) bean); + return new TraceFeignRetryer(getTracer(), (Retryer) bean); } else if (bean instanceof Client && !(bean instanceof TraceFeignClient)) { - return new TraceFeignClient(this.tracer, (Client) bean); + return new TraceFeignClient(getTracer(), (Client) bean); } return bean; } + private Tracer getTracer() { + if (this.tracer==null) { + this.tracer = this.beanFactory.getBean(Tracer.class); + } + return this.tracer; + } + @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignClientAutoConfiguration.java index 5d182202d..67951e650 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/feign/TraceFeignClientAutoConfiguration.java @@ -19,6 +19,7 @@ package org.springframework.cloud.sleuth.instrument.web.client.feign; import java.io.IOException; import java.lang.reflect.Type; +import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -49,8 +50,8 @@ import feign.Response; import feign.codec.Decoder; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} - * enables span information propagation when using Feign. + * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration + * Auto-configuration} enables span information propagation when using Feign. * * @author Marcin Grzejszczak * @@ -74,33 +75,44 @@ public class TraceFeignClientAutoConfiguration { return SleuthFeignBuilder.builder(tracer); } - @Bean - @ConditionalOnProperty(name = "spring.sleuth.feign.processor.enabled", matchIfMissing = true) - FeignBeanPostProcessor feignBeanPostProcessor(Tracer tracer) { - return new FeignBeanPostProcessor(tracer); + @Configuration + protected static class FeignBeanPostProcessorConfiguration { + + @Bean + @ConditionalOnProperty(name = "spring.sleuth.feign.processor.enabled", matchIfMissing = true) + FeignBeanPostProcessor feignBeanPostProcessor(BeanFactory beanFactory) { + return new FeignBeanPostProcessor(beanFactory); + } + } @Bean @Primary Decoder feignDecoder(final Tracer tracer) { - return new TraceFeignDecoder(tracer, new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)) { - @Override - public Object decode(Response response, Type type) - throws IOException, FeignException { - FeignRequestContext feignRequestContext = FeignRequestContext.getInstance(); - FeignResponseHeadersHolder feignResponseHeadersHolder = - new FeignResponseHeadersHolder(response.headers()); - feignResponseHeadersInjector().inject(feignRequestContext.getCurrentSpan(), feignResponseHeadersHolder); - return super.decode(Response.create(response.status(), - response.reason(), feignResponseHeadersHolder.responseHeaders, - response.body()), type); - } - }); + return new TraceFeignDecoder(tracer, + new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)) { + @Override + public Object decode(Response response, Type type) + throws IOException, FeignException { + FeignRequestContext feignRequestContext = FeignRequestContext + .getInstance(); + FeignResponseHeadersHolder feignResponseHeadersHolder = new FeignResponseHeadersHolder( + response.headers()); + feignResponseHeadersInjector().inject( + feignRequestContext.getCurrentSpan(), + feignResponseHeadersHolder); + return super.decode( + Response.create(response.status(), response.reason(), + feignResponseHeadersHolder.responseHeaders, + response.body()), + type); + } + }); } /** - * Sleuth {@link feign.RequestInterceptor} that either starts a new Span - * or continues an existing one if a retry takes place. + * Sleuth {@link feign.RequestInterceptor} that either starts a new Span or continues + * an existing one if a retry takes place. */ @Bean public RequestInterceptor traceIdRequestInterceptor(Tracer tracer) { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java index 8eee55cb2..bc936ed1a 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java @@ -18,12 +18,10 @@ package org.springframework.cloud.sleuth.log; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.sleuth.Tracer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -38,7 +36,7 @@ import org.springframework.context.annotation.Configuration; * @since 1.0.0 */ @Configuration -@ConditionalOnBean(Tracer.class) +@ConditionalOnProperty(value="spring.sleuth.enabled", matchIfMissing=true) public class SleuthLogAutoConfiguration { @Configuration diff --git a/spring-cloud-sleuth-stream/src/main/java/org/springframework/cloud/sleuth/stream/SleuthStreamAutoConfiguration.java b/spring-cloud-sleuth-stream/src/main/java/org/springframework/cloud/sleuth/stream/SleuthStreamAutoConfiguration.java index 4bb690a00..227f9c6fb 100644 --- a/spring-cloud-sleuth-stream/src/main/java/org/springframework/cloud/sleuth/stream/SleuthStreamAutoConfiguration.java +++ b/spring-cloud-sleuth-stream/src/main/java/org/springframework/cloud/sleuth/stream/SleuthStreamAutoConfiguration.java @@ -72,7 +72,7 @@ public class SleuthStreamAutoConfiguration { } @Bean - public StreamSpanListener sleuthTracer(HostLocator endpointLocator, + public StreamSpanListener sleuthStreamSpanListener(HostLocator endpointLocator, SpanMetricReporter spanMetricReporter) { return new StreamSpanListener(endpointLocator, spanMetricReporter); }