26
26
import org .aopalliance .intercept .MethodInterceptor ;
27
27
import org .aopalliance .intercept .MethodInvocation ;
28
28
import org .springframework .core .CollectionFactory ;
29
+ import org .springframework .core .convert .ConversionService ;
30
+ import org .springframework .core .convert .support .DefaultConversionService ;
29
31
import org .springframework .data .util .ClassTypeInformation ;
30
32
import org .springframework .data .util .TypeInformation ;
31
33
import org .springframework .util .Assert ;
@@ -43,6 +45,7 @@ class ProjectingMethodInterceptor implements MethodInterceptor {
43
45
44
46
private final ProjectionFactory factory ;
45
47
private final MethodInterceptor delegate ;
48
+ private final ConversionService conversionService ;
46
49
47
50
/**
48
51
* Creates a new {@link ProjectingMethodInterceptor} using the given {@link ProjectionFactory} and delegate
@@ -59,6 +62,7 @@ public ProjectingMethodInterceptor(ProjectionFactory factory, MethodInterceptor
59
62
60
63
this .factory = factory ;
61
64
this .delegate = delegate ;
65
+ this .conversionService = new DefaultConversionService ();
62
66
}
63
67
64
68
/*
@@ -75,13 +79,16 @@ public Object invoke(MethodInvocation invocation) throws Throwable {
75
79
}
76
80
77
81
TypeInformation <?> type = ClassTypeInformation .fromReturnTypeOf (invocation .getMethod ());
82
+ Class <?> rawType = type .getType ();
78
83
79
- if (type .isCollectionLike () && !ClassUtils .isPrimitiveArray (type . getType () )) {
84
+ if (type .isCollectionLike () && !ClassUtils .isPrimitiveArray (rawType )) {
80
85
return projectCollectionElements (asCollection (result ), type );
81
86
} else if (type .isMap ()) {
82
87
return projectMapValues ((Map <?, ?>) result , type );
88
+ } else if (conversionRequiredAndPossible (result , rawType )) {
89
+ return conversionService .convert (result , rawType );
83
90
} else {
84
- return getProjection (result , type . getType () );
91
+ return getProjection (result , rawType );
85
92
}
86
93
}
87
94
@@ -134,6 +141,23 @@ private Object getProjection(Object result, Class<?> returnType) {
134
141
: factory .createProjection (returnType , result );
135
142
}
136
143
144
+ /**
145
+ * Returns whether the source object needs to be converted to the given target type and whether we can convert it at
146
+ * all.
147
+ *
148
+ * @param source can be {@literal null}.
149
+ * @param targetType must not be {@literal null}.
150
+ * @return
151
+ */
152
+ private boolean conversionRequiredAndPossible (Object source , Class <?> targetType ) {
153
+
154
+ if (source == null || targetType .isInstance (source )) {
155
+ return false ;
156
+ }
157
+
158
+ return conversionService .canConvert (source .getClass (), targetType );
159
+ }
160
+
137
161
/**
138
162
* Turns the given value into a {@link Collection}. Will turn an array into a collection an wrap all other values into
139
163
* a single-element collection.
0 commit comments