DATACMNS-1246 - Minor optimization in QueryExecutorMethodInterceptor.
We now prevent the superfluous creation of a MethodParameter and TypeDescriptor instance in repository method execution in case the value to be returned already is an instance of the expected method return type.
This commit is contained in:
@@ -15,14 +15,17 @@
|
||||
*/
|
||||
package org.springframework.data.repository.core.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.CollectionFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.repository.util.NullableWrapper;
|
||||
import org.springframework.data.repository.util.QueryExecutionConverters;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Simple domain service to convert query results into a dedicated type.
|
||||
@@ -46,6 +49,27 @@ class QueryExecutionResultHandler {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-processes the given result of a query invocation to match the return type of the given method.
|
||||
*
|
||||
* @param result can be {@literal null}.
|
||||
* @param method must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public Object postProcessInvocationResult(Object result, Method method) {
|
||||
|
||||
Assert.notNull(method, "Method must not be null!");
|
||||
|
||||
if (method.getReturnType().isInstance(result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
MethodParameter parameter = new MethodParameter(method, -1);
|
||||
TypeDescriptor methodReturnTypeDescriptor = TypeDescriptor.nested(parameter, 0);
|
||||
|
||||
return postProcessInvocationResult(result, methodReturnTypeDescriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-processes the given result of a query invocation to the given type.
|
||||
*
|
||||
@@ -53,7 +77,7 @@ class QueryExecutionResultHandler {
|
||||
* @param returnTypeDesciptor can be {@literal null}, if so, no conversion is performed.
|
||||
* @return
|
||||
*/
|
||||
public Object postProcessInvocationResult(Object result, TypeDescriptor returnTypeDesciptor) {
|
||||
Object postProcessInvocationResult(Object result, TypeDescriptor returnTypeDesciptor) {
|
||||
|
||||
if (returnTypeDesciptor == null) {
|
||||
return result;
|
||||
@@ -73,7 +97,8 @@ class QueryExecutionResultHandler {
|
||||
|
||||
if (result != null) {
|
||||
return conversionService.canConvert(result.getClass(), expectedReturnType)
|
||||
? conversionService.convert(result, expectedReturnType) : result;
|
||||
? conversionService.convert(result, expectedReturnType)
|
||||
: result;
|
||||
}
|
||||
|
||||
if (Map.class.equals(expectedReturnType)) {
|
||||
|
||||
@@ -34,8 +34,6 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
@@ -476,12 +474,7 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware,
|
||||
|
||||
Object result = doInvoke(invocation);
|
||||
|
||||
// Looking up the TypeDescriptor for the return type - yes, this way o.O
|
||||
Method method = invocation.getMethod();
|
||||
MethodParameter parameter = new MethodParameter(method, -1);
|
||||
TypeDescriptor methodReturnTypeDescriptor = TypeDescriptor.nested(parameter, 0);
|
||||
|
||||
return resultHandler.postProcessInvocationResult(result, methodReturnTypeDescriptor);
|
||||
return resultHandler.postProcessInvocationResult(result, invocation.getMethod());
|
||||
}
|
||||
|
||||
private Object doInvoke(MethodInvocation invocation) throws Throwable {
|
||||
|
||||
@@ -26,8 +26,6 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
/**
|
||||
@@ -42,16 +40,16 @@ public class QueryExecutionResultHandlerUnitTests {
|
||||
@Test // DATACMNS-610
|
||||
public void convertsListsToSet() throws Exception {
|
||||
|
||||
TypeDescriptor descriptor = getTypeDescriptorFor("set");
|
||||
Method method = getMethod("set");
|
||||
List<Entity> source = Collections.singletonList(new Entity());
|
||||
|
||||
assertThat(handler.postProcessInvocationResult(source, descriptor), is(instanceOf(Set.class)));
|
||||
assertThat(handler.postProcessInvocationResult(source, method), is(instanceOf(Set.class)));
|
||||
}
|
||||
|
||||
@Test // DATACMNS-483
|
||||
public void turnsNullIntoJdk8Optional() throws Exception {
|
||||
|
||||
Object result = handler.postProcessInvocationResult(null, getTypeDescriptorFor("jdk8Optional"));
|
||||
Object result = handler.postProcessInvocationResult(null, getMethod("jdk8Optional"));
|
||||
assertThat(result, is((Object) Optional.empty()));
|
||||
}
|
||||
|
||||
@@ -61,7 +59,7 @@ public class QueryExecutionResultHandlerUnitTests {
|
||||
|
||||
Entity entity = new Entity();
|
||||
|
||||
Object result = handler.postProcessInvocationResult(entity, getTypeDescriptorFor("jdk8Optional"));
|
||||
Object result = handler.postProcessInvocationResult(entity, getMethod("jdk8Optional"));
|
||||
assertThat(result, is(instanceOf(Optional.class)));
|
||||
|
||||
Optional<Entity> optional = (Optional<Entity>) result;
|
||||
@@ -71,7 +69,7 @@ public class QueryExecutionResultHandlerUnitTests {
|
||||
@Test // DATACMNS-483
|
||||
public void turnsNullIntoGuavaOptional() throws Exception {
|
||||
|
||||
Object result = handler.postProcessInvocationResult(null, getTypeDescriptorFor("guavaOptional"));
|
||||
Object result = handler.postProcessInvocationResult(null, getMethod("guavaOptional"));
|
||||
assertThat(result, is((Object) com.google.common.base.Optional.absent()));
|
||||
}
|
||||
|
||||
@@ -81,7 +79,7 @@ public class QueryExecutionResultHandlerUnitTests {
|
||||
|
||||
Entity entity = new Entity();
|
||||
|
||||
Object result = handler.postProcessInvocationResult(entity, getTypeDescriptorFor("guavaOptional"));
|
||||
Object result = handler.postProcessInvocationResult(entity, getMethod("guavaOptional"));
|
||||
assertThat(result, is(instanceOf(com.google.common.base.Optional.class)));
|
||||
|
||||
com.google.common.base.Optional<Entity> optional = (com.google.common.base.Optional<Entity>) result;
|
||||
@@ -90,15 +88,11 @@ public class QueryExecutionResultHandlerUnitTests {
|
||||
|
||||
@Test // DATACMNS-917
|
||||
public void defaultsNullToEmptyMap() throws Exception {
|
||||
assertThat(handler.postProcessInvocationResult(null, getTypeDescriptorFor("map")), is(instanceOf(Map.class)));
|
||||
assertThat(handler.postProcessInvocationResult(null, getMethod("map")), is(instanceOf(Map.class)));
|
||||
}
|
||||
|
||||
private static TypeDescriptor getTypeDescriptorFor(String methodName) throws Exception {
|
||||
|
||||
Method method = Sample.class.getMethod(methodName);
|
||||
MethodParameter parameter = new MethodParameter(method, -1);
|
||||
|
||||
return TypeDescriptor.nested(parameter, 0);
|
||||
private static Method getMethod(String methodName) throws Exception {
|
||||
return Sample.class.getMethod(methodName);
|
||||
}
|
||||
|
||||
static interface Sample extends Repository<Entity, Long> {
|
||||
|
||||
Reference in New Issue
Block a user