DATACMNS-1556 - Remove capturing lambdas from hot code paths.

Replaced orElseThrow with if blocks. Introduce nullable RepositoryComposition.getMethod(Method) to avoid Optional handling in hot code paths.
This commit is contained in:
Mark Paluch
2019-07-23 10:54:57 +02:00
committed by Oliver Drotbohm
parent 972449ef2d
commit f1bc778098
3 changed files with 43 additions and 20 deletions

View File

@@ -180,7 +180,7 @@ class DefaultRepositoryInformation implements RepositoryInformation {
*/
@Override
public boolean isCustomMethod(Method method) {
return composition.findMethod(method).isPresent();
return composition.getMethod(method) != null;
}
/*
@@ -200,7 +200,7 @@ class DefaultRepositoryInformation implements RepositoryInformation {
public boolean isBaseClassMethod(Method method) {
Assert.notNull(method, "Method must not be null!");
return baseComposition.findMethod(method).isPresent();
return baseComposition.getMethod(method) != null;
}
/*

View File

@@ -37,6 +37,7 @@ import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.MethodLookup.InvokedMethod;
import org.springframework.data.repository.core.support.MethodLookup.MethodPredicate;
import org.springframework.data.util.Streamable;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
@@ -70,7 +71,7 @@ public class RepositoryComposition {
private static final RepositoryComposition EMPTY = new RepositoryComposition(RepositoryFragments.empty(),
MethodLookups.direct(), PASSTHRU_ARG_CONVERTER);
private final Map<Method, Optional<Method>> methodCache = new ConcurrentReferenceHashMap<>();
private final Map<Method, Method> methodCache = new ConcurrentReferenceHashMap<>();
private final @Getter RepositoryFragments fragments;
private final @Getter MethodLookup methodLookup;
private final @Getter BiFunction<Method, Object[], Object[]> argumentConverter;
@@ -192,8 +193,11 @@ public class RepositoryComposition {
*/
public Object invoke(Method method, Object... args) throws Throwable {
Method methodToCall = findMethod(method) //
.orElseThrow(() -> new IllegalArgumentException(String.format("No fragment found for method %s", method)));
Method methodToCall = getMethod(method);
if (methodToCall == null) {
throw new IllegalArgumentException(String.format("No fragment found for method %s", method));
}
ReflectionUtils.makeAccessible(methodToCall);
@@ -207,6 +211,18 @@ public class RepositoryComposition {
* @return
*/
public Optional<Method> findMethod(Method method) {
return Optional.ofNullable(getMethod(method));
}
/**
* Find the implementation method for the given {@link Method} invoked on the composite interface.
*
* @param method must not be {@literal null}.
* @return
* @since 2.2
*/
@Nullable
Method getMethod(Method method) {
return methodCache.computeIfAbsent(method,
key -> RepositoryFragments.findMethod(InvokedMethod.of(key), methodLookup, fragments::methods));
@@ -345,21 +361,26 @@ public class RepositoryComposition {
*/
public Object invoke(Method method, Object[] args) throws Throwable {
RepositoryFragment<?> fragment = fragmentCache.computeIfAbsent(method, key -> {
RepositoryFragment<?> fragment = fragmentCache.computeIfAbsent(method, this::findImplementationFragment);
Optional<?> optional = fragment.getImplementation();
return stream().filter(it -> it.hasMethod(key)) //
.filter(it -> it.getImplementation().isPresent()) //
.findFirst()
.orElseThrow(() -> new IllegalArgumentException(String.format("No fragment found for method %s", key)));
});
if (!optional.isPresent()) {
throw new IllegalArgumentException(String.format("No implementation found for method %s", method));
}
Object target = fragment.getImplementation().orElseThrow(
() -> new IllegalArgumentException(String.format("No implementation found for method %s", method)));
return method.invoke(target, args);
return method.invoke(optional.get(), args);
}
private static Optional<Method> findMethod(InvokedMethod invokedMethod, MethodLookup lookup,
private RepositoryFragment<?> findImplementationFragment(Method key) {
return stream().filter(it -> it.hasMethod(key)) //
.filter(it -> it.getImplementation().isPresent()) //
.findFirst()
.orElseThrow(() -> new IllegalArgumentException(String.format("No fragment found for method %s", key)));
}
@Nullable
private static Method findMethod(InvokedMethod invokedMethod, MethodLookup lookup,
Supplier<Stream<Method>> methodStreamSupplier) {
for (MethodPredicate methodPredicate : lookup.getLookups()) {
@@ -369,11 +390,11 @@ public class RepositoryComposition {
.findFirst();
if (resolvedMethod.isPresent()) {
return resolvedMethod;
return resolvedMethod.get();
}
}
return Optional.empty();
return null;
}
/*

View File

@@ -160,10 +160,11 @@ public interface RepositoryFragment<T> {
private final Optional<Class<T>> interfaceClass;
private final T implementation;
private final Optional<T> optionalImplementation;
/**
* Creates a new {@link ImplementedRepositoryFragment} for the given interface class and implementation.
*
*
* @param interfaceClass must not be {@literal null}.
* @param implementation must not be {@literal null}.
*/
@@ -181,6 +182,7 @@ public interface RepositoryFragment<T> {
this.interfaceClass = interfaceClass;
this.implementation = implementation;
this.optionalImplementation = Optional.of(implementation);
}
/*
@@ -198,7 +200,7 @@ public interface RepositoryFragment<T> {
*/
@Override
public Optional<T> getImplementation() {
return Optional.of(implementation);
return optionalImplementation;
}
/*