Spring Data Redis의 문서를 보다 보면 아래와 같은 예제가 보인다.
// inject the template as ListOperations
@Resource(name="redisTemplate")
private ListOperations<String, String> listOps;
Spring Boot의 RedisAutoConfiguration에서는 RedisTemplate과 StringRedisTemplate bean을 자동 설정해주고 있다.
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
그런데 처음 예제는 redisTemplate이란 이름의 ListOperations object를 inject 하고 있다.
언뜻 생각해보기엔 ListOperations가 RedisTemplate의 상위 interface인가 싶지만 살펴보면 RedisTemplate의 Hierarchy와 관련이 없다.
어떻게 ListOperations객체가 redisTemplate bean name으로 호출하여 inject 될 수 있는 것일까?
ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition 에서 DefaultListableBeanFactory가 TypeConverter를 통해 조회 시 BeanUtils.findEditorByConvention method를 호출하게 된다.
해당 유틸에선 targetTypeName + "Editor" 규칙의 위치에 있는 PropertyEditor 상속 클래스를 찾아 해당 PropertyEditor를 통해 해당 객체를 convert 하게 된다.
Spring Data Redis는 PropertyEditor를 다음과 같이 구현해두었다.
각각은 binding된 타입의 + "Editor" 이름으로 설정되어 있다.
따라서 redisTemplate이란 이름의 ListOperations 가 선언되어 있으면 ListOperationsEditor가 수행되어 원래 redisTemplate에 해당하는 bean을 전달받아 ListOperations object로 convert 한다.
ListOperationsEditor의 내용은 다음과 같다.
class ListOperationsEditor extends PropertyEditorSupport {
public void setValue(Object value) {
if (value instanceof RedisOperations) {
super.setValue(((RedisOperations) value).opsForList());
} else {
throw new IllegalArgumentException("Editor supports only conversion of type " + RedisOperations.class);
}
}
}
bean을 선언하지 않고 이렇게 사용하면 해당 autowired 객체의 generic type 매개 변수를 dynamic 하게 사용할 수 있고 또 autowired 처리되는 부분마다 재생성을 하여 간섭에서도 자유로울 수 있다.
반복적으로 사용하는 generic type 매개 변수의 data binding을 쓰는 경우 이 방법을 사용하는 것이 좋을 듯하다.
'Study > Java' 카테고리의 다른 글
JDK 12 ~ JDK 17 사이 추가된 language specification feature (0) | 2021.09.15 |
---|---|
JDK 17 New Features (0) | 2021.09.15 |
Spring Boot에서 Resilience4j 사용해보기 (0) | 2021.09.09 |
Java lambda expression(람다 표현식)을 사용한 지연 연산(Lazy Evaluation) (0) | 2021.08.27 |
maven central repository에 라이브러리 배포하기 (0) | 2021.07.20 |
Spring Boot Data Redis 사용해보기 (0) | 2021.06.09 |
Spring Boot 2.5 Release Notes (0) | 2021.05.26 |
Spring Reference Documentation 한글 번역 (0) | 2021.04.13 |
spring boot에서 webjars 사용하기 (0) | 2021.03.23 |
JDK 16 New Features (0) | 2021.03.18 |