1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.beans.factory.config;
18
19 import java.io.IOException;
20 import java.io.ObjectInputStream;
21 import java.io.Serializable;
22 import java.lang.annotation.Annotation;
23 import java.lang.reflect.Field;
24 import java.lang.reflect.ParameterizedType;
25 import java.lang.reflect.Type;
26
27 import org.springframework.core.GenericCollectionTypeResolver;
28 import org.springframework.core.GenericTypeResolver;
29 import org.springframework.core.MethodParameter;
30 import org.springframework.core.ParameterNameDiscoverer;
31 import org.springframework.core.ResolvableType;
32 import org.springframework.util.Assert;
33
34
35
36
37
38
39
40
41
42 @SuppressWarnings("serial")
43 public class DependencyDescriptor implements Serializable {
44
45 private transient MethodParameter methodParameter;
46
47 private transient Field field;
48
49 private Class<?> declaringClass;
50
51 private Class<?> containingClass;
52
53 private String methodName;
54
55 private Class<?>[] parameterTypes;
56
57 private int parameterIndex;
58
59 private String fieldName;
60
61 private final boolean required;
62
63 private final boolean eager;
64
65 private int nestingLevel = 1;
66
67 private transient Annotation[] fieldAnnotations;
68
69
70
71
72
73
74
75
76 public DependencyDescriptor(MethodParameter methodParameter, boolean required) {
77 this(methodParameter, required, true);
78 }
79
80
81
82
83
84
85
86
87 public DependencyDescriptor(MethodParameter methodParameter, boolean required, boolean eager) {
88 Assert.notNull(methodParameter, "MethodParameter must not be null");
89 this.methodParameter = methodParameter;
90 this.declaringClass = methodParameter.getDeclaringClass();
91 this.containingClass = methodParameter.getContainingClass();
92 if (this.methodParameter.getMethod() != null) {
93 this.methodName = methodParameter.getMethod().getName();
94 this.parameterTypes = methodParameter.getMethod().getParameterTypes();
95 }
96 else {
97 this.parameterTypes = methodParameter.getConstructor().getParameterTypes();
98 }
99 this.parameterIndex = methodParameter.getParameterIndex();
100 this.required = required;
101 this.eager = eager;
102 }
103
104
105
106
107
108
109
110 public DependencyDescriptor(Field field, boolean required) {
111 this(field, required, true);
112 }
113
114
115
116
117
118
119
120
121 public DependencyDescriptor(Field field, boolean required, boolean eager) {
122 Assert.notNull(field, "Field must not be null");
123 this.field = field;
124 this.declaringClass = field.getDeclaringClass();
125 this.fieldName = field.getName();
126 this.required = required;
127 this.eager = eager;
128 }
129
130
131
132
133
134 public DependencyDescriptor(DependencyDescriptor original) {
135 this.methodParameter = (original.methodParameter != null ? new MethodParameter(original.methodParameter) : null);
136 this.field = original.field;
137 this.declaringClass = original.declaringClass;
138 this.containingClass = original.containingClass;
139 this.methodName = original.methodName;
140 this.parameterTypes = original.parameterTypes;
141 this.parameterIndex = original.parameterIndex;
142 this.fieldName = original.fieldName;
143 this.required = original.required;
144 this.eager = original.eager;
145 this.nestingLevel = original.nestingLevel;
146 this.fieldAnnotations = original.fieldAnnotations;
147 }
148
149
150
151
152
153
154
155 public MethodParameter getMethodParameter() {
156 return this.methodParameter;
157 }
158
159
160
161
162
163
164 public Field getField() {
165 return this.field;
166 }
167
168
169
170
171 public boolean isRequired() {
172 return this.required;
173 }
174
175
176
177
178
179 public boolean isEager() {
180 return this.eager;
181 }
182
183
184
185
186
187
188 public void increaseNestingLevel() {
189 this.nestingLevel++;
190 if (this.methodParameter != null) {
191 this.methodParameter.increaseNestingLevel();
192 }
193 }
194
195
196
197
198
199
200 public void setContainingClass(Class<?> containingClass) {
201 this.containingClass = containingClass;
202 if (this.methodParameter != null) {
203 GenericTypeResolver.resolveParameterType(this.methodParameter, containingClass);
204 }
205 }
206
207
208
209
210 public ResolvableType getResolvableType() {
211 return (this.field != null ? ResolvableType.forField(this.field, this.nestingLevel, this.containingClass) :
212 ResolvableType.forMethodParameter(this.methodParameter));
213 }
214
215
216
217
218
219
220
221 public boolean fallbackMatchAllowed() {
222 return false;
223 }
224
225
226
227
228
229 public DependencyDescriptor forFallbackMatch() {
230 return new DependencyDescriptor(this) {
231 @Override
232 public boolean fallbackMatchAllowed() {
233 return true;
234 }
235 };
236 }
237
238
239
240
241
242
243
244 public void initParameterNameDiscovery(ParameterNameDiscoverer parameterNameDiscoverer) {
245 if (this.methodParameter != null) {
246 this.methodParameter.initParameterNameDiscovery(parameterNameDiscoverer);
247 }
248 }
249
250
251
252
253
254 public String getDependencyName() {
255 return (this.field != null ? this.field.getName() : this.methodParameter.getParameterName());
256 }
257
258
259
260
261
262 public Class<?> getDependencyType() {
263 if (this.field != null) {
264 if (this.nestingLevel > 1) {
265 Type type = this.field.getGenericType();
266 for (int i = 2; i <= this.nestingLevel; i++) {
267 if (type instanceof ParameterizedType) {
268 Type[] args = ((ParameterizedType) type).getActualTypeArguments();
269 type = args[args.length - 1];
270 }
271 }
272 if (type instanceof Class) {
273 return (Class<?>) type;
274 }
275 else if (type instanceof ParameterizedType) {
276 Type arg = ((ParameterizedType) type).getRawType();
277 if (arg instanceof Class) {
278 return (Class<?>) arg;
279 }
280 }
281 return Object.class;
282 }
283 else {
284 return this.field.getType();
285 }
286 }
287 else {
288 return this.methodParameter.getNestedParameterType();
289 }
290 }
291
292
293
294
295
296 public Class<?> getCollectionType() {
297 return (this.field != null ?
298 GenericCollectionTypeResolver.getCollectionFieldType(this.field, this.nestingLevel) :
299 GenericCollectionTypeResolver.getCollectionParameterType(this.methodParameter));
300 }
301
302
303
304
305
306 public Class<?> getMapKeyType() {
307 return (this.field != null ?
308 GenericCollectionTypeResolver.getMapKeyFieldType(this.field, this.nestingLevel) :
309 GenericCollectionTypeResolver.getMapKeyParameterType(this.methodParameter));
310 }
311
312
313
314
315
316 public Class<?> getMapValueType() {
317 return (this.field != null ?
318 GenericCollectionTypeResolver.getMapValueFieldType(this.field, this.nestingLevel) :
319 GenericCollectionTypeResolver.getMapValueParameterType(this.methodParameter));
320 }
321
322
323
324
325 public Annotation[] getAnnotations() {
326 if (this.field != null) {
327 if (this.fieldAnnotations == null) {
328 this.fieldAnnotations = this.field.getAnnotations();
329 }
330 return this.fieldAnnotations;
331 }
332 else {
333 return this.methodParameter.getParameterAnnotations();
334 }
335 }
336
337
338
339
340
341
342 private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
343
344 ois.defaultReadObject();
345
346
347 try {
348 if (this.fieldName != null) {
349 this.field = this.declaringClass.getDeclaredField(this.fieldName);
350 }
351 else {
352 if (this.methodName != null) {
353 this.methodParameter = new MethodParameter(
354 this.declaringClass.getDeclaredMethod(this.methodName, this.parameterTypes), this.parameterIndex);
355 }
356 else {
357 this.methodParameter = new MethodParameter(
358 this.declaringClass.getDeclaredConstructor(this.parameterTypes), this.parameterIndex);
359 }
360 for (int i = 1; i < this.nestingLevel; i++) {
361 this.methodParameter.increaseNestingLevel();
362 }
363 }
364 }
365 catch (Throwable ex) {
366 throw new IllegalStateException("Could not find original class structure", ex);
367 }
368 }
369
370 }