DATACMNS-1102 - Avoid superfluous recreation of ConversionService for projections.

For repository query methods with a dynamic projection parameter, the ResultProcessor is recreated with the type handed to the method. This results in recreation of the ProjectingConverter, which previously recreated a DefaultConversionService instance (for fallback conversions), which is rather expensive due to the reflection lookups checking for the presence of libraries on the classpath.

This is now avoided by using copying methods that reuse the initially created DefaultConversionService.
This commit is contained in:
Oliver Gierke
2017-07-02 21:37:02 +02:00
parent 8a0dffea67
commit c3c5e7e331

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.repository.query;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@@ -44,6 +46,7 @@ import org.springframework.util.Assert;
* @author Christoph Strobl
* @since 1.12
*/
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class ResultProcessor {
private final QueryMethod method;
@@ -90,9 +93,7 @@ public class ResultProcessor {
Assert.notNull(accessor, "Parameter accessor must not be null!");
return accessor.getDynamicProjection()//
.map(it -> new ResultProcessor(method, factory, it))//
.orElse(this);
return accessor.getDynamicProjection().map(this::withType).orElse(this);
}
/**
@@ -160,6 +161,12 @@ public class ResultProcessor {
return (T) converter.convert(source);
}
private ResultProcessor withType(Class<?> type) {
ReturnedType returnedType = ReturnedType.of(type, method.getDomainClass(), factory);
return new ResultProcessor(method, converter.withType(returnedType), factory, returnedType);
}
/**
* Creates a new {@link Collection} for the given source. Will try to create an instance of the source collection's
* type first falling back to creating an approximate collection if the former fails.
@@ -235,7 +242,30 @@ public class ResultProcessor {
private final @NonNull ReturnedType type;
private final @NonNull ProjectionFactory factory;
private final ConversionService conversionService = new DefaultConversionService();
private final @NonNull ConversionService conversionService;
/**
* Creates a new {@link ProjectingConverter} for the given {@link ReturnedType} and {@link ProjectionFactory}.
*
* @param type must not be {@literal null}.
* @param factory must not be {@literal null}.
*/
ProjectingConverter(ReturnedType type, ProjectionFactory factory) {
this(type, factory, new DefaultConversionService());
}
/**
* Creates a new {@link ProjectingConverter} for the given {@link ReturnedType}.
*
* @param type must not be {@literal null}.
* @return
*/
ProjectingConverter withType(ReturnedType type) {
Assert.notNull(type, "ReturnedType must not be null!");
return new ProjectingConverter(type, factory, conversionService);
}
/*
* (non-Javadoc)