最近使用restTemplate的时候遇到了很多问题,在排查问题的时候了解了下其中的源码。(这块没有文档,真的难受。)
spring boot 提供了RestTemplate自动配置类 RestTemplateAutoConfiguration。
@Configuration
@AutoConfigureAfter(HttpMessageConvertersAutoConfiguration.class)
@ConditionalOnClass(RestTemplate.class)
public class RestTemplateAutoConfiguration {
private final ObjectProvider<HttpMessageConverters> messageConverters;
private final ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers;
public RestTemplateAutoConfiguration(
ObjectProvider<HttpMessageConverters> messageConverters,
ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers) {
this.messageConverters = messageConverters;
this.restTemplateCustomizers = restTemplateCustomizers;
}
……
}
这里看到这个类是在消息转换器自动配置之后配置的,我们观察到spring 注入属性的时候用到了ObjectProvider这个类,这个类是spring 4.3出来的新特性,spring 4之后推荐构造函数注入,并且在4.3之后可以使用构造函数隐式注入,即如果没有在构造函数上加@Autowired,spring会从使用改类中默认的构造器注入,当然如果多个构造器就必须加上此注解了。ObjectProvider(spring里面为BeanObjectProvider)这个类解决了bean为空,和bean有多个实例的问题,里面包含getObject、getIfAvailable、getIfUnique等方法。
@Bean
@ConditionalOnMissingBean
public RestTemplateBuilder restTemplateBuilder() {
RestTemplateBuilder builder = new RestTemplateBuilder();
HttpMessageConverters converters = this.messageConverters.getIfUnique();
if (converters != null) {
builder = builder.messageConverters(converters.getConverters());
}
List<RestTemplateCustomizer> customizers = this.restTemplateCustomizers
.orderedStream().collect(Collectors.toList());
if (!CollectionUtils.isEmpty(customizers)) {
builder = builder.customizers(customizers);
}
return builder;
}
这个方法会构造一个RestTemplateBuilder交给spring管理,中间通过getIfUnique()获取到单例的HttpMessageConverters 和restTemplateCustomizers,把其中所有自动配置的消息转换器和所有的RestTemplateCustomizer(用于自定义restTemplate的回调接口)加入这个RestTemplateBuilder,然后返回一个完整的实例。当然方法首先new了一个RestTemplateBuilder,看看它的构造器给我们干了什么。
public RestTemplateBuilder(RestTemplateCustomizer... customizers) {
Assert.notNull(customizers, "Customizers must not be null");
this.detectRequestFactory = true;
this.rootUri = null;
this.messageConverters = null;
this.requestFactorySupplier = null;
this.uriTemplateHandler = null;
this.errorHandler = null;
this.basicAuthentication = null;
this.restTemplateCustomizers = Collections
.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(customizers)));
this.requestFactoryCustomizer = new RequestFactoryCustomizer();
this.interceptors = Collections.emptySet();
}
这里给detectRequestFactory赋值成了true,目的是为了后面自动检测ClientHttpRequestFactory。
接下来我们使用的时候通常会将RestTemplateBuilder注入到要使用到bean里面,使用之前spring自动配置给我们带来的功能,并且我们可以附加很多功能,比如自定义 的HttpMessageConverter、自定义的RestTemplate、自定义的ClientHttpRequestFactory、自定义的异常处理和请求拦截器。
最终的目的是为了得到一个供我们使用的RestTemplate。我们通常会使用build()方法构建。 接下来看看build方法做了什么。
public RestTemplate build() {
return build(RestTemplate.class);
}
/**
* Build a new {@link RestTemplate} instance of the specified type and configure it
* using this builder.
* @param <T> the type of rest template
* @param restTemplateClass the template type to create
* @return a configured {@link RestTemplate} instance.
* @see RestTemplateBuilder#build()
* @see #configure(RestTemplate)
*/
public <T extends RestTemplate> T build(Class<T> restTemplateClass) {
return configure(BeanUtils.instantiateClass(restTemplateClass));
}
在我们没有自定义RestTemplate我们会调用上面方法,他会调用下面方法,帮我们创建一个RestTemplate的实例作为configure的参数,再来看configure方法:
public <T extends RestTemplate> T configure(T restTemplate) {
configureRequestFactory(restTemplate);
if (!CollectionUtils.isEmpty(this.messageConverters)) {
restTemplate.setMessageConverters(new ArrayList<>(this.messageConverters));
}
if (this.uriTemplateHandler != null) {
restTemplate.setUriTemplateHandler(this.uriTemplateHandler);
}
if (this.errorHandler != null) {
restTemplate.setErrorHandler(this.errorHandler);
}
if (this.rootUri != null) {
RootUriTemplateHandler.addTo(restTemplate, this.rootUri);
}
if (this.basicAuthentication != null) {
restTemplate.getInterceptors().add(this.basicAuthentication);
}
restTemplate.getInterceptors().addAll(this.interceptors);
if (!CollectionUtils.isEmpty(this.restTemplateCustomizers)) {
for (RestTemplateCustomizer customizer : this.restTemplateCustomizers) {
customizer.customize(restTemplate);
}
}
return restTemplate;
}
这里就是把刚刚自动配置的消息转换器,错误处理器,配置一些URI模板,URI路径的模板,发送请求的basic认证拦截器和其他一些拦截器(ClientHttpRequestInterceptor),一些自定义的restTemplate的会调接口。
然后继续看其中的
configureRequestFactory(restTemplate);
private void configureRequestFactory(RestTemplate restTemplate) {
ClientHttpRequestFactory requestFactory = null;
if (this.requestFactorySupplier != null) {
requestFactory = this.requestFactorySupplier.get();
}
else if (this.detectRequestFactory) {
requestFactory = new ClientHttpRequestFactorySupplier().get();
}
if (requestFactory != null) {
if (this.requestFactoryCustomizer != null) {
this.requestFactoryCustomizer.accept(requestFactory);
}
restTemplate.setRequestFactory(requestFactory);
}
}