최근 RestClient를 사용하게 되어 문서를 읽던 중,
사용 범위에 따른 3가지 방식을 소개하는데 이 부분의 의미가 너무 헷갈렸다.
요약하자면 대충 이런 내용인데
최대한 좁은 범위에 적용하려면:
- 자동 구성된 RestClient.Builder를 주입받아 호출해라. 인스턴스는 stateful하다
- Builder에 대한 변경은 이후에 생성된 모든 클라이언트에 반영된다
- 동일한 빌더로 여러 클라이언트를 생성하려면 clone()을 사용하여 빌더를 복제하는 것을 고려해라
내가 상상한 코드는 대충 아래와 같았음
class A {
A(@Autowired RestClient.Builder builder) {
// builder 설정 변경
}
}
class B {
B(@Autowired RestClient.Builder builder) {
// ❓❓ 여기서 A의 변경 사항이 적용 된다고? ❓❓
}
}
동일한 빌더
라는 건 같은 참조 값을 의미하는 것이었음
void some(@Autowired RestClient.Builder builder) {
builder.defaultHeader(...);
var clientA = builder.defaultHeader(CHANGE).build();
....
var clientB = builder.build();
}
이런 경우에 복제(clone)해서 쓰라는 것.
내가 저 설명을 보고 쫄게된 이유는 RestClient.Builder
bean이 어떻게 구성되며 작동하는지 몰랐기 때문이다.
RestClient.Builder
는 RestClientAutoConfiguration
이 bean으로 자동으로 구성해준다.
@AutoConfiguration(after = { HttpMessageConvertersAutoConfiguration.class, SslAutoConfiguration.class })
@ConditionalOnClass(RestClient.class)
@Conditional(NotReactiveWebApplicationCondition.class)
public class RestClientAutoConfiguration {
@Bean
@Scope("prototype")
@ConditionalOnMissingBean
RestClient.Builder restClientBuilder(RestClientBuilderConfigurer restClientBuilderConfigurer) {
....
}
}
위 코드를 통해
@AutoConfiguration
, NotReactiveWebApplicationCondition
)RestClient.Builder
는 요청이 있을 때 마다 새로 생성됨을 알 수 있다(@Scope("prototype")
)아래와 같은 경우에 테스트가 실패하니 clone 하라는 것임
@Test
void test(@Autowired RestClient.Builder builder) {
//given
var server = MockRestServiceServer.bindTo(builder).build();
builder.defaultHeader(ACCEPT, APPLICATION_JSON_VALUE);
//when
var clientA = builder.defaultHeader(ACCEPT, TEXT_PLAIN_VALUE).build(); // 👈 clone() 하시오
server.expect(requestTo("a"))
.andExpect(header(ACCEPT, TEXT_PLAIN_VALUE))
.andRespond(withSuccess());
var clientB = builder.build();
server.expect(requestTo("b"))
.andExpect(header(ACCEPT, APPLICATION_JSON_VALUE))
.andRespond(withSuccess());
//then
clientA.get().uri("a").retrieve().toBodilessEntity();
clientB.get().uri("b").retrieve().toBodilessEntity();
}
결국 builder 특성상 당연한 이야기였고 문서가 친절한 것이었다,,, 쫄지말자!