|
1 | 1 | /*
|
2 |
| - * Copyright 2012-2018 the original author or authors. |
| 2 | + * Copyright 2012-2019 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
18 | 18 |
|
19 | 19 | import java.lang.reflect.Modifier;
|
20 | 20 | import java.util.Map;
|
| 21 | +import java.util.function.BiConsumer; |
21 | 22 |
|
22 | 23 | import javax.annotation.PostConstruct;
|
23 | 24 |
|
|
27 | 28 | import com.fasterxml.jackson.databind.Module;
|
28 | 29 | import com.fasterxml.jackson.databind.module.SimpleModule;
|
29 | 30 |
|
| 31 | +import org.springframework.beans.BeanUtils; |
30 | 32 | import org.springframework.beans.BeansException;
|
31 | 33 | import org.springframework.beans.factory.BeanFactory;
|
32 | 34 | import org.springframework.beans.factory.BeanFactoryAware;
|
33 | 35 | import org.springframework.beans.factory.HierarchicalBeanFactory;
|
34 | 36 | import org.springframework.beans.factory.ListableBeanFactory;
|
| 37 | +import org.springframework.boot.jackson.JsonComponent.Scope; |
35 | 38 | import org.springframework.core.ResolvableType;
|
36 |
| -import org.springframework.core.annotation.AnnotationUtils; |
| 39 | +import org.springframework.core.annotation.MergedAnnotation; |
| 40 | +import org.springframework.core.annotation.MergedAnnotations; |
| 41 | +import org.springframework.core.annotation.MergedAnnotations.SearchStrategy; |
| 42 | +import org.springframework.util.Assert; |
| 43 | +import org.springframework.util.ObjectUtils; |
37 | 44 |
|
38 | 45 | /**
|
39 | 46 | * Spring Bean and Jackson {@link Module} to register {@link JsonComponent} annotated
|
@@ -70,88 +77,78 @@ private void addJsonBeans(ListableBeanFactory beanFactory) {
|
70 | 77 | Map<String, Object> beans = beanFactory
|
71 | 78 | .getBeansWithAnnotation(JsonComponent.class);
|
72 | 79 | for (Object bean : beans.values()) {
|
73 |
| - JsonComponent annotation = AnnotationUtils.findAnnotation(bean.getClass(), |
74 |
| - JsonComponent.class); |
75 |
| - addJsonBean(bean, annotation); |
| 80 | + addJsonBean(bean); |
76 | 81 | }
|
77 | 82 | }
|
78 | 83 |
|
79 |
| - private void addJsonBean(Object bean, JsonComponent annotation) { |
| 84 | + private void addJsonBean(Object bean) { |
| 85 | + MergedAnnotation<JsonComponent> annotation = MergedAnnotations |
| 86 | + .from(bean.getClass(), SearchStrategy.EXHAUSTIVE) |
| 87 | + .get(JsonComponent.class); |
| 88 | + Class<?>[] types = annotation.getClassArray("type"); |
| 89 | + Scope scope = annotation.getEnum("scope", JsonComponent.Scope.class); |
| 90 | + addJsonBean(bean, types, scope); |
| 91 | + } |
| 92 | + |
| 93 | + private void addJsonBean(Object bean, Class<?>[] types, Scope scope) { |
80 | 94 | if (bean instanceof JsonSerializer) {
|
81 |
| - addSerializerForTypes((JsonSerializer<?>) bean, annotation.handle(), |
82 |
| - annotation.handleClasses()); |
| 95 | + addJsonSerializerBean((JsonSerializer<?>) bean, scope, types); |
83 | 96 | }
|
84 |
| - if (bean instanceof KeyDeserializer) { |
85 |
| - addKeyDeserializerForTypes((KeyDeserializer) bean, |
86 |
| - annotation.handleClasses()); |
| 97 | + else if (bean instanceof JsonDeserializer) { |
| 98 | + addJsonDeserializerBean((JsonDeserializer<?>) bean, types); |
87 | 99 | }
|
88 |
| - if (bean instanceof JsonDeserializer) { |
89 |
| - addDeserializerForTypes((JsonDeserializer<?>) bean, |
90 |
| - annotation.handleClasses()); |
| 100 | + else if (bean instanceof KeyDeserializer) { |
| 101 | + addKeyDeserializerBean((KeyDeserializer) bean, types); |
91 | 102 | }
|
92 | 103 | for (Class<?> innerClass : bean.getClass().getDeclaredClasses()) {
|
93 |
| - if (!Modifier.isAbstract(innerClass.getModifiers()) |
94 |
| - && (JsonSerializer.class.isAssignableFrom(innerClass) |
95 |
| - || JsonDeserializer.class.isAssignableFrom(innerClass) |
96 |
| - || KeyDeserializer.class.isAssignableFrom(innerClass))) { |
97 |
| - try { |
98 |
| - addJsonBean(innerClass.newInstance(), annotation); |
99 |
| - } |
100 |
| - catch (Exception ex) { |
101 |
| - throw new IllegalStateException(ex); |
102 |
| - } |
| 104 | + if (isSuitableInnerClass(innerClass)) { |
| 105 | + Object innerInstance = BeanUtils.instantiateClass(innerClass); |
| 106 | + addJsonBean(innerInstance, types, scope); |
103 | 107 | }
|
104 | 108 | }
|
105 | 109 | }
|
106 | 110 |
|
107 |
| - @SuppressWarnings({ "unchecked" }) |
108 |
| - private <T> void addSerializerForTypes(JsonSerializer<T> serializer, |
109 |
| - JsonComponent.Handle handle, Class<?>[] types) { |
110 |
| - for (Class<?> type : types) { |
111 |
| - addSerializerWithType(serializer, handle, (Class<T>) type); |
112 |
| - } |
113 |
| - |
114 |
| - if (types.length == 0) { |
115 |
| - ResolvableType type = ResolvableType.forClass(JsonSerializer.class, |
116 |
| - serializer.getClass()); |
117 |
| - addSerializerWithType(serializer, handle, (Class<T>) type.resolveGeneric()); |
118 |
| - } |
| 111 | + private boolean isSuitableInnerClass(Class<?> innerClass) { |
| 112 | + return !Modifier.isAbstract(innerClass.getModifiers()) |
| 113 | + && (JsonSerializer.class.isAssignableFrom(innerClass) |
| 114 | + || JsonDeserializer.class.isAssignableFrom(innerClass) |
| 115 | + || KeyDeserializer.class.isAssignableFrom(innerClass)); |
119 | 116 | }
|
120 | 117 |
|
121 |
| - private <T> void addSerializerWithType(JsonSerializer<T> serializer, |
122 |
| - JsonComponent.Handle handle, Class<? extends T> type) { |
123 |
| - if (JsonComponent.Handle.KEYS.equals(handle)) { |
124 |
| - addKeySerializer(type, serializer); |
125 |
| - } |
126 |
| - else { |
127 |
| - addSerializer(type, serializer); |
128 |
| - } |
| 118 | + @SuppressWarnings("unchecked") |
| 119 | + private <T> void addJsonSerializerBean(JsonSerializer<T> serializer, |
| 120 | + JsonComponent.Scope scope, Class<?>[] types) { |
| 121 | + Class<T> baseType = (Class<T>) ResolvableType |
| 122 | + .forClass(JsonSerializer.class, serializer.getClass()).resolveGeneric(); |
| 123 | + addBeanToModule(serializer, baseType, types, |
| 124 | + (scope == Scope.VALUES) ? this::addSerializer : this::addKeySerializer); |
| 125 | + |
129 | 126 | }
|
130 | 127 |
|
131 |
| - @SuppressWarnings({ "unchecked" }) |
132 |
| - private <T> void addDeserializerForTypes(JsonDeserializer<T> deserializer, |
| 128 | + @SuppressWarnings("unchecked") |
| 129 | + private <T> void addJsonDeserializerBean(JsonDeserializer<T> deserializer, |
133 | 130 | Class<?>[] types) {
|
134 |
| - for (Class<?> type : types) { |
135 |
| - addDeserializer((Class<T>) type, deserializer); |
136 |
| - } |
137 |
| - |
138 |
| - if (types.length == 0) { |
139 |
| - addDeserializerWithDeducedType(deserializer); |
140 |
| - } |
| 131 | + Class<T> baseType = (Class<T>) ResolvableType |
| 132 | + .forClass(JsonDeserializer.class, deserializer.getClass()) |
| 133 | + .resolveGeneric(); |
| 134 | + addBeanToModule(deserializer, baseType, types, this::addDeserializer); |
141 | 135 | }
|
142 | 136 |
|
143 |
| - @SuppressWarnings({ "unchecked" }) |
144 |
| - private <T> void addDeserializerWithDeducedType(JsonDeserializer<T> deserializer) { |
145 |
| - ResolvableType type = ResolvableType.forClass(JsonDeserializer.class, |
146 |
| - deserializer.getClass()); |
147 |
| - addDeserializer((Class<T>) type.resolveGeneric(), deserializer); |
148 |
| - |
| 137 | + private void addKeyDeserializerBean(KeyDeserializer deserializer, Class<?>[] types) { |
| 138 | + Assert.notEmpty(types, "Type must be specified for KeyDeserializer"); |
| 139 | + addBeanToModule(deserializer, Object.class, types, this::addKeyDeserializer); |
149 | 140 | }
|
150 | 141 |
|
151 |
| - private void addKeyDeserializerForTypes(KeyDeserializer deserializer, |
152 |
| - Class<?>[] types) { |
| 142 | + @SuppressWarnings("unchecked") |
| 143 | + private <E, T> void addBeanToModule(E element, Class<T> baseType, Class<?>[] types, |
| 144 | + BiConsumer<Class<T>, E> consumer) { |
| 145 | + if (ObjectUtils.isEmpty(types)) { |
| 146 | + consumer.accept(baseType, element); |
| 147 | + return; |
| 148 | + } |
153 | 149 | for (Class<?> type : types) {
|
154 |
| - addKeyDeserializer(type, deserializer); |
| 150 | + Assert.isAssignable(baseType, type); |
| 151 | + consumer.accept((Class<T>) type, element); |
155 | 152 | }
|
156 | 153 | }
|
157 | 154 |
|
|
0 commit comments