diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java index 810959960..da6b1914c 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java @@ -18,20 +18,18 @@ package org.springframework.cloud.sleuth.instrument.web.client; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import javax.annotation.PostConstruct; import brave.http.HttpTracing; import brave.spring.web.TracingClientHttpRequestInterceptor; +import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.web.client.RestTemplateCustomizer; import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration; -import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @@ -64,27 +62,14 @@ public class TraceWebClientAutoConfiguration { @Configuration protected static class TraceInterceptorConfiguration { - @Autowired - private ApplicationContext applicationContext; + @Autowired private TracingClientHttpRequestInterceptor clientInterceptor; - @Autowired - private TracingClientHttpRequestInterceptor clientInterceptor; - - @Bean - @Order - RestTemplateCustomizer traceRestTemplateCustomizer() { + @Bean @Order RestTemplateCustomizer traceRestTemplateCustomizer() { return new TraceRestTemplateCustomizer(this.clientInterceptor); } - @PostConstruct - public void init() { - Map restTemplates = BeanFactoryUtils - .beansOfTypeIncludingAncestors(this.applicationContext, - RestTemplate.class); - for (RestTemplate restTemplate : restTemplates.values()) { - new RestTemplateInterceptorInjector( - this.clientInterceptor).inject(restTemplate); - } + @Bean TraceRestTemplateBPP traceRestTemplateBPP(BeanFactory beanFactory) { + return new TraceRestTemplateBPP(beanFactory); } } } @@ -139,4 +124,35 @@ class TraceRestTemplateCustomizer implements RestTemplateCustomizer { new RestTemplateInterceptorInjector(this.interceptor) .inject(restTemplate); } +} + +class TraceRestTemplateBPP implements BeanPostProcessor { + + private final BeanFactory beanFactory; + private TracingClientHttpRequestInterceptor interceptor; + + TraceRestTemplateBPP(BeanFactory beanFactory) { + this.beanFactory = beanFactory; + } + + @Override public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + return bean; + } + + @Override public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + if (bean instanceof RestTemplate) { + RestTemplate rt = (RestTemplate) bean; + new RestTemplateInterceptorInjector(interceptor()).inject(rt); + } + return bean; + } + + private TracingClientHttpRequestInterceptor interceptor() { + if (this.interceptor == null) { + this.interceptor = this.beanFactory.getBean(TracingClientHttpRequestInterceptor.class); + } + return this.interceptor; + } } \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java new file mode 100644 index 000000000..9944ad5a5 --- /dev/null +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/client/GH846Test.java @@ -0,0 +1,85 @@ +/* + * Copyright 2013-2018 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 + * + * http://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.sleuth.instrument.web.client; + +import javax.annotation.PostConstruct; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.client.RestTemplate; + +@SpringBootTest(classes = GH846Test.App.class, webEnvironment=WebEnvironment.NONE) +@RunWith(SpringRunner.class) +public class GH846Test { + + @Autowired + private MyBean myBean; + + @Test + public void doit() throws Exception { + int count = myBean.listAndCount(); + Assert.assertEquals("Change detected in RestTemplate interceptor *after* @PostConstruct", count, myBean.getCountAtPostConstruct()); + } + + @EnableAutoConfiguration + @Configuration + static class App { + @Bean + public RestTemplate myRestTemplate() { + return new RestTemplate(); + } + + @Bean + public MyBean myBean() { + return new MyBean(); + } + } + + + static class MyBean { + @Autowired + private RestTemplate restTemplate; + + /** Number of interceptors registered in the RestTemplate during @PostConstruct */ + private int countAtPostConstruct; + + @PostConstruct + public void init() { + countAtPostConstruct = listAndCount(); + } + + public int listAndCount() { + for(ClientHttpRequestInterceptor interceptor: restTemplate.getInterceptors()) { + System.out.println(interceptor); + } + return restTemplate.getInterceptors().size(); + } + + public int getCountAtPostConstruct() { + return countAtPostConstruct; + } + } +}