Skip to content

Commit d06129d

Browse files
committed
InterceptingHttpAccessor uses internal ArrayList for sorting
Also caches InterceptingClientHttpRequestFactory (if applicable) Issue: SPR-16137
1 parent 48c2cc1 commit d06129d

File tree

4 files changed

+75
-29
lines changed

4 files changed

+75
-29
lines changed

spring-web/src/main/java/org/springframework/http/client/support/HttpAccessor.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,11 +34,12 @@
3434
* such as the {@link ClientHttpRequestFactory} to operate on.
3535
*
3636
* <p>Not intended to be used directly.
37-
* See {@link org.springframework.web.client.RestTemplate}.
37+
* See {@link org.springframework.web.client.RestTemplate} for an entry point.
3838
*
3939
* @author Arjen Poutsma
4040
* @author Juergen Hoeller
4141
* @since 3.0
42+
* @see ClientHttpRequestFactory
4243
* @see org.springframework.web.client.RestTemplate
4344
*/
4445
public abstract class HttpAccessor {
@@ -56,6 +57,7 @@ public abstract class HttpAccessor {
5657
* <p><b>Note that the standard JDK HTTP library does not support the HTTP PATCH method.
5758
* Configure the Apache HttpComponents or OkHttp request factory to enable PATCH.</b>
5859
* @see #createRequest(URI, HttpMethod)
60+
* @see SimpleClientHttpRequestFactory
5961
* @see org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory
6062
* @see org.springframework.http.client.OkHttp3ClientHttpRequestFactory
6163
*/

spring-web/src/main/java/org/springframework/http/client/support/InterceptingHttpAccessor.java

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,43 +23,83 @@
2323
import org.springframework.http.client.ClientHttpRequestFactory;
2424
import org.springframework.http.client.ClientHttpRequestInterceptor;
2525
import org.springframework.http.client.InterceptingClientHttpRequestFactory;
26+
import org.springframework.lang.Nullable;
2627
import org.springframework.util.CollectionUtils;
2728

2829
/**
29-
* Base class for {@link org.springframework.web.client.RestTemplate} and other HTTP accessing gateway helpers, adding
30-
* interceptor-related properties to {@link HttpAccessor}'s common properties.
30+
* Base class for {@link org.springframework.web.client.RestTemplate}
31+
* and other HTTP accessing gateway helpers, adding interceptor-related
32+
* properties to {@link HttpAccessor}'s common properties.
3133
*
32-
* <p>Not intended to be used directly. See {@link org.springframework.web.client.RestTemplate}.
34+
* <p>Not intended to be used directly.
35+
* See {@link org.springframework.web.client.RestTemplate} for an entry point.
3336
*
3437
* @author Arjen Poutsma
38+
* @author Juergen Hoeller
39+
* @since 3.0
40+
* @see ClientHttpRequestInterceptor
41+
* @see InterceptingClientHttpRequestFactory
42+
* @see org.springframework.web.client.RestTemplate
3543
*/
3644
public abstract class InterceptingHttpAccessor extends HttpAccessor {
3745

38-
private List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
46+
private final List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
47+
48+
@Nullable
49+
private volatile ClientHttpRequestFactory interceptingRequestFactory;
50+
3951

4052
/**
41-
* Sets the request interceptors that this accessor should use.
53+
* Set the request interceptors that this accessor should use.
54+
* <p>The interceptors will get sorted according to their order
55+
* once the {@link ClientHttpRequestFactory} will be built.
56+
* @see #getRequestFactory()
57+
* @see AnnotationAwareOrderComparator
4258
*/
4359
public void setInterceptors(List<ClientHttpRequestInterceptor> interceptors) {
44-
AnnotationAwareOrderComparator.sort(interceptors);
45-
this.interceptors = interceptors;
60+
// Take getInterceptors() List as-is when passed in here
61+
if (this.interceptors != interceptors) {
62+
this.interceptors.clear();
63+
this.interceptors.addAll(interceptors);
64+
AnnotationAwareOrderComparator.sort(this.interceptors);
65+
}
4666
}
4767

4868
/**
49-
* Return the request interceptor that this accessor uses.
69+
* Return the request interceptors that this accessor uses.
70+
* <p>The returned {@link List} is active and may get appended to.
5071
*/
5172
public List<ClientHttpRequestInterceptor> getInterceptors() {
52-
return interceptors;
73+
return this.interceptors;
74+
}
75+
76+
/**
77+
* {@inheritDoc}
78+
*/
79+
@Override
80+
public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
81+
super.setRequestFactory(requestFactory);
82+
this.interceptingRequestFactory = null;
5383
}
5484

85+
/**
86+
* Overridden to expose an {@link InterceptingClientHttpRequestFactory}
87+
* if necessary.
88+
* @see #getInterceptors()
89+
*/
5590
@Override
5691
public ClientHttpRequestFactory getRequestFactory() {
57-
ClientHttpRequestFactory delegate = super.getRequestFactory();
58-
if (!CollectionUtils.isEmpty(getInterceptors())) {
59-
return new InterceptingClientHttpRequestFactory(delegate, getInterceptors());
92+
List<ClientHttpRequestInterceptor> interceptors = getInterceptors();
93+
if (!CollectionUtils.isEmpty(interceptors)) {
94+
ClientHttpRequestFactory factory = this.interceptingRequestFactory;
95+
if (factory == null) {
96+
factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);
97+
this.interceptingRequestFactory = factory;
98+
}
99+
return factory;
60100
}
61101
else {
62-
return delegate;
102+
return super.getRequestFactory();
63103
}
64104
}
65105

spring-web/src/main/java/org/springframework/web/client/RestTemplate.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters
237237
}
238238

239239
/**
240-
* Return the message body converters.
240+
* Return the list of message body converters.
241+
* <p>The returned {@link List} is active and may get appended to.
241242
*/
242243
public List<HttpMessageConverter<?>> getMessageConverters() {
243244
return this.messageConverters;

spring-web/src/test/java/org/springframework/http/client/support/InterceptingHttpAccessorTests.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,9 +16,6 @@
1616

1717
package org.springframework.http.client.support;
1818

19-
import static org.junit.Assert.*;
20-
21-
import java.io.IOException;
2219
import java.util.Arrays;
2320
import java.util.List;
2421

@@ -32,6 +29,8 @@
3229
import org.springframework.http.client.ClientHttpRequestInterceptor;
3330
import org.springframework.http.client.ClientHttpResponse;
3431

32+
import static org.junit.Assert.*;
33+
3534
/**
3635
* Tests for {@link InterceptingHttpAccessor}.
3736
*
@@ -40,7 +39,7 @@
4039
public class InterceptingHttpAccessorTests {
4140

4241
@Test
43-
public void getInterceptors() throws Exception {
42+
public void getInterceptors() {
4443
TestInterceptingHttpAccessor accessor = new TestInterceptingHttpAccessor();
4544
List<ClientHttpRequestInterceptor> interceptors = Arrays.asList(
4645
new SecondClientHttpRequestInterceptor(),
@@ -55,22 +54,25 @@ public void getInterceptors() throws Exception {
5554
assertThat(accessor.getInterceptors().get(2), Matchers.instanceOf(ThirdClientHttpRequestInterceptor.class));
5655
}
5756

57+
5858
private class TestInterceptingHttpAccessor extends InterceptingHttpAccessor {
5959
}
6060

61+
6162
@Order(1)
6263
private class FirstClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
64+
6365
@Override
64-
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
65-
ClientHttpRequestExecution execution) throws IOException {
66+
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
6667
return null;
6768
}
6869
}
6970

71+
7072
private class SecondClientHttpRequestInterceptor implements ClientHttpRequestInterceptor, Ordered {
73+
7174
@Override
72-
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
73-
ClientHttpRequestExecution execution) throws IOException {
75+
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
7476
return null;
7577
}
7678

@@ -80,12 +82,13 @@ public int getOrder() {
8082
}
8183
}
8284

85+
8386
private class ThirdClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
87+
8488
@Override
85-
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
86-
ClientHttpRequestExecution execution) throws IOException {
89+
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
8790
return null;
8891
}
8992
}
9093

91-
}
94+
}

0 commit comments

Comments
 (0)