Skip to content

Commit

Permalink
Cache query method metadata to avoid repeated calculations.
Browse files Browse the repository at this point in the history
We now calculate information about query methods in RepositoryInformationSupport lazily and keep it around to avoid repeated calculations that involve traversals over declared method and Stream allocations.

Fixes GH-3066.
  • Loading branch information
odrotbohm committed Mar 25, 2024
1 parent 0c9afae commit ec78e1b
Showing 1 changed file with 57 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.HashSet;
import java.util.Arrays;
import java.util.Set;
import java.util.function.Supplier;

Expand All @@ -43,6 +42,7 @@ public abstract class RepositoryInformationSupport implements RepositoryInformat

private final Supplier<RepositoryMetadata> metadata;
private final Supplier<Class<?>> repositoryBaseClass;
private final Supplier<DefaultQueryMethods> queryMethods;

public RepositoryInformationSupport(Supplier<RepositoryMetadata> metadata, Supplier<Class<?>> repositoryBaseClass) {

Expand All @@ -51,25 +51,12 @@ public RepositoryInformationSupport(Supplier<RepositoryMetadata> metadata, Suppl

this.metadata = Lazy.of(metadata);
this.repositoryBaseClass = Lazy.of(repositoryBaseClass);
this.queryMethods = Lazy.of(this::calculateQueryMethods);
}

@Override
public Streamable<Method> getQueryMethods() {

Set<Method> result = new HashSet<>();

for (Method method : getRepositoryInterface().getMethods()) {
method = ClassUtils.getMostSpecificMethod(method, getRepositoryInterface());
if (isQueryMethodCandidate(method)) {
result.add(method);
}
}

return Streamable.of(Collections.unmodifiableSet(result));
}

private RepositoryMetadata getMetadata() {
return metadata.get();
return queryMethods.get().methods;
}

@Override
Expand Down Expand Up @@ -139,21 +126,12 @@ public TypeInformation<?> getIdTypeInformation() {

@Override
public boolean hasCustomMethod() {
return queryMethods.get().hasCustomMethod;
}

Class<?> repositoryInterface = getRepositoryInterface();

// No detection required if no typing interface was configured
if (isGenericRepositoryInterface(repositoryInterface)) {
return false;
}

for (Method method : repositoryInterface.getMethods()) {
if (isCustomMethod(method) && !isBaseClassMethod(method)) {
return true;
}
}

return false;
@Override
public boolean hasQueryMethods() {
return queryMethods.get().hasQueryMethod;
}

/**
Expand All @@ -178,4 +156,52 @@ protected boolean isQueryMethodCandidate(Method method) {
&& !Modifier.isStatic(method.getModifiers()) //
&& (isQueryAnnotationPresentOn(method) || !isCustomMethod(method) && !isBaseClassMethod(method));
}

private RepositoryMetadata getMetadata() {
return metadata.get();
}

private final DefaultQueryMethods calculateQueryMethods() {

Class<?> repositoryInterface = getRepositoryInterface();

return new DefaultQueryMethods(Streamable.of(Arrays.stream(repositoryInterface.getMethods())
.map(it -> ClassUtils.getMostSpecificMethod(it, repositoryInterface))
.filter(this::isQueryMethodCandidate)
.toList()), calculateHasCustomMethod(repositoryInterface));
}

private final boolean calculateHasCustomMethod(Class<?> repositoryInterface) {

// No detection required if no typing interface was configured
if (isGenericRepositoryInterface(repositoryInterface)) {
return false;
}

for (Method method : repositoryInterface.getMethods()) {
if (isCustomMethod(method) && !isBaseClassMethod(method)) {
return true;
}
}

return false;
}

/**
* Information about query methods to allow canonical computation and reuse of that information.
*
* @author Oliver Drotbohm
*/
private static class DefaultQueryMethods {

private final Streamable<Method> methods;
private final boolean hasCustomMethod, hasQueryMethod;

DefaultQueryMethods(Streamable<Method> methods, boolean hasCustomMethod) {

this.methods = methods;
this.hasCustomMethod = hasCustomMethod;
this.hasQueryMethod = !methods.isEmpty();
}
}
}

0 comments on commit ec78e1b

Please sign in to comment.