토비의 봄 TV 2회 - 수퍼 타입 토큰IT/Spring Framework2018. 2. 3. 23:40
Table of Contents
(시청일 : 20170924)
- https://www.youtube.com/watch?v=01sdXvZSjcI : 스프링에서 사용되는 ParameterizedTypeReference의 작동 원리인 Super Type Token의 동작 원리와 활용법을 알아봅니다.
■ Type Token : 타입 정보를 key로 넘겨서 value를 리턴
■ Type Safe Token 예제 코드
public class TypeToken {
static Class TypeSafeMap {
Map<Class<?>, Object> map = new HashMap<>();
<T> void put(Class<T> clazz, T value) {
map.put(clazz, value);
}
<T> T get(Class<T> clazz) {
return clazz.cast(map.get(clazz));
}
}
public static void main(String[] args) throws Exception {
TypeSafeMap m = new TypeSafeMap();
m.put(Integer.class, 1);
m.put(String.class, "String");
m.put(List.class, Arrays.asList(1,2,3));
System.out.println(m.get(Integer.class));
System.out.println(m.get(String.class));
System.out.println(m.get(List.class));
}
}
■ Super Type Token 예제 코드 => 메모리 누수를 야기하는 등 좋지 않은 코드라서, 2.5회에서 개선 됨.
public class SuperTypeToken {
static Class TypeSafeMap {
Map<TypeReference<?>, Object> map = new HashMap<>();
<T> void put(TypeReference<T> tr, T value) {
map.put(tr, value);
}
<T> T get(TypeReference<T> tr) {
if (tr.type instanceof Class<?>)
return ((Class<T>)tr.type).cast(map.get(tr));
else
return ((Class<T>)((ParameterizedType)tr.type).getRawType()).cast(map.get(tr)); // TR<List<String>>
}
}
static class TypeReference<T> {
Type type;
public TypeReference() {
Type stype = getClass().getGenericSuperclass();
if (stype instanceof ParameterizedType) {
this.type = ((ParameterizedType) stype).getActualTypeArguments()[0];
} else throw new RuntimeException();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass().getGenericSuperclass() != o.getClass().getGenericSuperclass()) return false;
TypeReference that = (TypeReference) o;
return type.equals(that.type);
}
@Override
public int hashCode() {
return type.hashCode();
}
}
public static void main(String[] args) throws Exception {
TypeReference m = new TypeSafeMap();
m.put(new TypeReference<Integer>() {}, 1);
m.put(new TypeReference<String>() {}, "String");
m.put(new TypeReference<List<Integer>>() {}, Arrays.asList(1,2,3)); // List<Integer>
m.put(new TypeReference<List<String>>() {}, Arrays.asList("a","b","c")); // List<String>
m.put(new TypeReference<List<List<String>>>() {}, Arrays.asList(Arrays.asList("a"),Arrays.asList("b"),Arrays.asList("c"))); // List<String>
System.out.println(m.get(new TypeReference<Integer>() {}));
System.out.println(m.get(new TypeReference<String>() {}));
System.out.println(m.get(new TypeReference<List<Integer>>() {}));
System.out.println(m.get(new TypeReference<List<String>>() {}));
System.out.println(m.get(new TypeReference<List<List<String>>>() {}));
}
}
■ 위의 코드와 유사한 Spring 3.2 버전 이상에서 지원하는
ParameterizedTypeReference의 사용 예제
public class SpringTypeReference {
public static void main(String[] args) {
ParameterizedTypeReference<?> typeRef = new ParameterizedTypeReference<List<Map<Set<Integer>, String>>>() {};
System.out.println(typeRef.getType());
}
}
■ ParameterizedTypeReference의 사용 사례
@SpringBootApplication
public class TobyTv002liveApplication {
public static void main(String[] args) {
SpringApplication.run(TobyTv002liveApplication.class, args);
}
@RestController
public static class MyController {
@RequestMapping("/")
public List<User> users() {
return Arrays.asList(new User("A"), new User("B"), new User("C"));
}
}
public static class User {
String name;
public User(String name) {
this.name = name;
}
public User() {
}
public String getName() {
return name;
}
@Override
public String toString() {
return "User[" +
"name='" + name + '\'' +
']';
}
}
}
public class SpringTypeReference {
public static void main(String[] args) {
RestTemplate rt = new RestTemplate();
// 타입 safe하지 않음
// System.out.println(users.get(0).getName("name"));
HttpMethod.Get, null, new ParameterizedTypeReference<List<User>>() {}).getBody();
users.forEach(System.out::println );
}
}
'IT > Spring Framework' 카테고리의 다른 글
토비의 봄 TV 10회 스프링 리액티브 프로그래밍 (6) AsyncRestTemplate의 콜백 헬과 중복 작업 문제 (0) | 2018.02.03 |
---|---|
토비의 봄 TV 9회 스프링 리액티브 프로그래밍 (5) 비동기 RestTemplate과 비동기 MVC/Servlet (0) | 2018.02.03 |
토비의 봄 TV 1회 - 재사용성과 다이나믹 디스패치, 더블 디스패치 (0) | 2018.02.03 |
토비의 봄 TV 8회 스프링 리액티브 프로그래밍 (4) 자바와 스프링의 비동기 기술 (0) | 2018.02.03 |
토비의 봄 TV 7회 스프링 리액티브 프로그래밍 (3) - Reactive Streams - Schedulers (0) | 2018.02.03 |
@DEAN :: Dean Story
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!