DATACMNS-1108 - Add repository configuration infrastructure.

Add config infrastructure for ReactiveQueryMethodEvaluationContextProvider.

Original Pull Request: #454
This commit is contained in:
Mark Paluch
2020-06-30 11:13:04 +02:00
committed by Christoph Strobl
parent edcf1a0562
commit 0671862ed8
11 changed files with 197 additions and 52 deletions

View File

@@ -18,7 +18,9 @@ package org.springframework.data.spel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import org.springframework.data.util.Streamable;
@@ -28,6 +30,7 @@ import org.springframework.expression.spel.ast.CompoundExpression;
import org.springframework.expression.spel.ast.MethodReference;
import org.springframework.expression.spel.ast.PropertyOrFieldReference;
import org.springframework.expression.spel.standard.SpelExpression;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
@@ -46,6 +49,15 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
this.dependencies = dependencies;
}
/**
* Return an empty {@link ExpressionDependencies} object.
*
* @return the empty dependencies.
*/
public static ExpressionDependencies empty() {
return EMPTY;
}
/**
* Discover all expression dependencies that are referenced in the {@link SpelNode expression root}.
*
@@ -53,7 +65,7 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
* @return a set of {@link ExpressionDependencies}.
*/
public static ExpressionDependencies discover(Expression expression) {
return expression instanceof SpelExpression ? discover(((SpelExpression) expression).getAST(), true) : EMPTY;
return expression instanceof SpelExpression ? discover(((SpelExpression) expression).getAST(), true) : empty();
}
/**
@@ -74,7 +86,7 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
}
});
return new ExpressionDependencies(Collections.unmodifiableList(dependencies));
return new ExpressionDependencies(dependencies);
}
private static void collectDependencies(SpelNode node, int compoundPosition,
@@ -94,7 +106,25 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
}
}
/*
/**
* Create new {@link ExpressionDependencies} that contains all dependencies from this object and {@code other}. The
* merged dependencies are guaranteed to not contain duplicates.
*
* @param other the other {@link ExpressionDependencies} object.
* @return new merged {@link ExpressionDependencies} object.
*/
public ExpressionDependencies mergeWith(ExpressionDependencies other) {
Assert.notNull(other, "Other ExpressionDependencies must not be null");
Set<ExpressionDependency> dependencySet = new LinkedHashSet<>(this.dependencies.size() + other.dependencies.size());
dependencySet.addAll(this.dependencies);
dependencySet.addAll(other.dependencies);
return new ExpressionDependencies(new ArrayList<>(dependencySet));
}
/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
@@ -103,7 +133,7 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
return this.dependencies.iterator();
}
/*
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@@ -119,7 +149,7 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
return ObjectUtils.nullSafeEquals(dependencies, that.dependencies);
}
/*
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@@ -196,7 +226,7 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
return symbol;
}
/*
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@@ -218,7 +248,7 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
return ObjectUtils.nullSafeEquals(symbol, that.symbol);
}
/*
/*
* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@@ -230,7 +260,7 @@ public class ExpressionDependencies implements Streamable<ExpressionDependencies
return result;
}
/*
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/

View File

@@ -99,7 +99,8 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex
this.extensions = extensions;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.spel.EvaluationContextProvider#getEvaluationContext(Object)
*/
@Override
@@ -107,8 +108,9 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex
return doGetEvaluationContext(rootObject, getExtensions(it -> true));
}
/* (non-Javadoc)
* @see org.springframework.data.spel.EvaluationContextProvider#getEvaluationContext(Object, Collection, ExpressionDependencies)
/*
* (non-Javadoc)
* @see org.springframework.data.spel.EvaluationContextProvider#getEvaluationContext(Object, ExpressionDependencies)
*/
@Override
public StandardEvaluationContext getEvaluationContext(Object rootObject, ExpressionDependencies dependencies) {

View File

@@ -25,16 +25,15 @@ import org.springframework.expression.EvaluationContext;
* @author Mark Paluch
* @since 2.4
*/
@FunctionalInterface
public interface ReactiveEvaluationContextProvider {
public interface ReactiveEvaluationContextProvider extends EvaluationContextProvider {
/**
* Returns an {@link EvaluationContext} built using the given parameter values.
*
* @param rootObject the root object to set in the {@link EvaluationContext}.
* @return mono emitting the {@link EvaluationContext}.
* @return a mono that emits exactly one {@link EvaluationContext}.
*/
Mono<? extends EvaluationContext> getEvaluationContext(Object rootObject);
Mono<? extends EvaluationContext> getEvaluationContextLater(Object rootObject);
/**
* Returns a tailored {@link EvaluationContext} built using the given parameter values and considering
@@ -44,11 +43,11 @@ public interface ReactiveEvaluationContextProvider {
*
* @param rootObject the root object to set in the {@link EvaluationContext}.
* @param dependencies the requested expression dependencies to be available.
* @return mono emitting the {@link EvaluationContext}.
* @return a mono that emits exactly one {@link EvaluationContext}.
* @since 2.4
*/
default Mono<? extends EvaluationContext> getEvaluationContext(Object rootObject,
default Mono<? extends EvaluationContext> getEvaluationContextLater(Object rootObject,
ExpressionDependencies dependencies) {
return getEvaluationContext(rootObject);
return getEvaluationContextLater(rootObject);
}
}

View File

@@ -27,7 +27,6 @@ import org.springframework.core.ResolvableType;
import org.springframework.data.spel.spi.EvaluationContextExtension;
import org.springframework.data.spel.spi.ExtensionIdAware;
import org.springframework.data.spel.spi.ReactiveEvaluationContextExtension;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
@@ -37,6 +36,7 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
* {@link ReactiveEvaluationContextExtension} and {@link EvaluationContextExtension} instances.
*
* @author Mark Paluch
* @since 2.4
*/
public class ReactiveExtensionAwareEvaluationContextProvider implements ReactiveEvaluationContextProvider {
@@ -49,32 +49,67 @@ public class ReactiveExtensionAwareEvaluationContextProvider implements Reactive
evaluationContextProvider = new ExtensionAwareEvaluationContextProvider();
}
/**
* Create a new {@link ReactiveExtensionAwareEvaluationContextProvider} with extensions looked up lazily from the
* given {@link ListableBeanFactory}.
*
* @param beanFactory the {@link ListableBeanFactory} to lookup extensions from.
*/
public ReactiveExtensionAwareEvaluationContextProvider(ListableBeanFactory beanFactory) {
evaluationContextProvider = new ExtensionAwareEvaluationContextProvider(beanFactory);
}
/**
* Creates a new {@link ReactiveExtensionAwareEvaluationContextProvider} for the given
* {@link EvaluationContextExtension}s.
*
* @param extensions must not be {@literal null}.
*/
public ReactiveExtensionAwareEvaluationContextProvider(Collection<? extends ExtensionIdAware> extensions) {
evaluationContextProvider = new ExtensionAwareEvaluationContextProvider(extensions);
}
public ReactiveExtensionAwareEvaluationContextProvider(
Lazy<? extends Collection<? extends ExtensionIdAware>> extensions) {
evaluationContextProvider = new ExtensionAwareEvaluationContextProvider(extensions);
/*
* (non-Javadoc)
* @see org.springframework.data.spel.EvaluationContextProvider#getEvaluationContext(Object)
*/
@Override
public EvaluationContext getEvaluationContext(Object rootObject) {
return evaluationContextProvider.getEvaluationContext(rootObject);
}
/*
* (non-Javadoc)
* @see org.springframework.data.spel.EvaluationContextProvider#getEvaluationContext(java.lang.Object, org.springframework.data.spel.ExpressionDependencies)
*/
@Override
public Mono<StandardEvaluationContext> getEvaluationContext(Object rootObject) {
public EvaluationContext getEvaluationContext(Object rootObject, ExpressionDependencies dependencies) {
return evaluationContextProvider.getEvaluationContext(rootObject, dependencies);
}
/*
* (non-Javadoc)
* @see org.springframework.data.spel.ReactiveEvaluationContextProvider#getEvaluationContextLater(java.lang.Object)
*/
@Override
public Mono<StandardEvaluationContext> getEvaluationContextLater(Object rootObject) {
return getExtensions(it -> true) //
.map(it -> evaluationContextProvider.doGetEvaluationContext(rootObject, it));
}
/*
* (non-Javadoc)
* @see org.springframework.data.spel.ReactiveEvaluationContextProvider#getEvaluationContextLater(java.lang.Object, org.springframework.data.spel.ExpressionDependencies)
*/
@Override
public Mono<StandardEvaluationContext> getEvaluationContext(Object rootObject, ExpressionDependencies dependencies) {
public Mono<StandardEvaluationContext> getEvaluationContextLater(Object rootObject,
ExpressionDependencies dependencies) {
return getExtensions(it -> dependencies.stream().anyMatch(it::provides)) //
.map(it -> evaluationContextProvider.doGetEvaluationContext(rootObject, it));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Mono<List<EvaluationContextExtension>> getExtensions(
Predicate<EvaluationContextExtensionInformation> extensionFilter) {
@@ -83,6 +118,7 @@ public class ReactiveExtensionAwareEvaluationContextProvider implements Reactive
return Flux.fromIterable(extensions).concatMap(it -> {
if (it instanceof EvaluationContextExtension) {
EvaluationContextExtension extension = (EvaluationContextExtension) it;
EvaluationContextExtensionInformation information = evaluationContextProvider.getOrCreateInformation(extension);
@@ -114,13 +150,10 @@ public class ReactiveExtensionAwareEvaluationContextProvider implements Reactive
}).collectList();
}
private ResolvableType getExtensionType(ExtensionIdAware extensionCandidate) {
private static ResolvableType getExtensionType(ExtensionIdAware extensionCandidate) {
ResolvableType extensionType = ResolvableType
return ResolvableType
.forMethodReturnType(ReflectionUtils.findRequiredMethod(extensionCandidate.getClass(), "getExtension"))
.getGeneric(0);
return extensionType;
}
}