diff --git a/src/main/java/org/springframework/data/repository/query/ExtensionAwareQueryMethodEvaluationContextProvider.java b/src/main/java/org/springframework/data/repository/query/ExtensionAwareQueryMethodEvaluationContextProvider.java index 15d3b6589..a025cb3ab 100644 --- a/src/main/java/org/springframework/data/repository/query/ExtensionAwareQueryMethodEvaluationContextProvider.java +++ b/src/main/java/org/springframework/data/repository/query/ExtensionAwareQueryMethodEvaluationContextProvider.java @@ -30,7 +30,6 @@ import org.aopalliance.intercept.MethodInvocation; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider; import org.springframework.data.spel.spi.EvaluationContextExtension; -import org.springframework.data.util.Lazy; import org.springframework.data.util.Streamable; import org.springframework.expression.EvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext; @@ -52,7 +51,7 @@ import org.springframework.util.StringUtils; */ public class ExtensionAwareQueryMethodEvaluationContextProvider implements QueryMethodEvaluationContextProvider { - private final Lazy delegate; + private final ExtensionAwareEvaluationContextProvider delegate; /** * Creates a new {@link ExtensionAwareQueryMethodEvaluationContextProvider}. @@ -64,7 +63,7 @@ public class ExtensionAwareQueryMethodEvaluationContextProvider implements Query Assert.notNull(beanFactory, "ListableBeanFactory must not be null!"); - this.delegate = Lazy.of(() -> new ExtensionAwareEvaluationContextProvider(() -> getExtensionsFrom(beanFactory))); + this.delegate = new ExtensionAwareEvaluationContextProvider(beanFactory); } /** @@ -77,7 +76,7 @@ public class ExtensionAwareQueryMethodEvaluationContextProvider implements Query Assert.notNull(extensions, "EvaluationContextExtensions must not be null!"); - this.delegate = Lazy.of(new org.springframework.data.spel.ExtensionAwareEvaluationContextProvider(extensions)); + this.delegate = new org.springframework.data.spel.ExtensionAwareEvaluationContextProvider(extensions); } /* @@ -87,7 +86,7 @@ public class ExtensionAwareQueryMethodEvaluationContextProvider implements Query @Override public > EvaluationContext getEvaluationContext(T parameters, Object[] parameterValues) { - StandardEvaluationContext evaluationContext = delegate.get().getEvaluationContext(parameterValues); + StandardEvaluationContext evaluationContext = delegate.getEvaluationContext(parameterValues); evaluationContext.setVariables(collectVariables(parameters, parameterValues)); diff --git a/src/main/java/org/springframework/data/spel/ExtensionAwareEvaluationContextProvider.java b/src/main/java/org/springframework/data/spel/ExtensionAwareEvaluationContextProvider.java index 26b800511..af2a40a88 100644 --- a/src/main/java/org/springframework/data/spel/ExtensionAwareEvaluationContextProvider.java +++ b/src/main/java/org/springframework/data/spel/ExtensionAwareEvaluationContextProvider.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Supplier; import java.util.stream.Collectors; import org.springframework.beans.factory.BeanFactory; @@ -37,6 +36,7 @@ import org.springframework.data.spel.EvaluationContextExtensionInformation.Exten import org.springframework.data.spel.EvaluationContextExtensionInformation.RootObjectInformation; import org.springframework.data.spel.spi.EvaluationContextExtension; import org.springframework.data.spel.spi.Function; +import org.springframework.data.util.Lazy; import org.springframework.data.util.Optionals; import org.springframework.expression.AccessException; import org.springframework.expression.EvaluationContext; @@ -66,7 +66,7 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex private final Map, EvaluationContextExtensionInformation> extensionInformationCache = new ConcurrentHashMap<>(); - private final Supplier> extensions; + private final Lazy> extensions; private ListableBeanFactory beanFactory; ExtensionAwareEvaluationContextProvider() { @@ -81,7 +81,7 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex */ public ExtensionAwareEvaluationContextProvider(ListableBeanFactory beanFactory) { - this(() -> getExtensionsFrom(beanFactory)); + this(Lazy.of(() -> getExtensionsFrom(beanFactory))); this.beanFactory = beanFactory; } @@ -92,7 +92,7 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex * @param extensions must not be {@literal null}. */ public ExtensionAwareEvaluationContextProvider(Collection extensions) { - this(() -> extensions); + this(Lazy.of(extensions)); } /* (non-Javadoc) diff --git a/src/test/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProviderUnitTests.java b/src/test/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProviderUnitTests.java index 13a25d587..344f40ea2 100755 --- a/src/test/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProviderUnitTests.java +++ b/src/test/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProviderUnitTests.java @@ -16,6 +16,9 @@ package org.springframework.data.repository.query; import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; import lombok.RequiredArgsConstructor; @@ -31,10 +34,13 @@ import java.util.concurrent.atomic.AtomicInteger; import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; +import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider; import org.springframework.data.spel.spi.EvaluationContextExtension; import org.springframework.data.spel.spi.Function; import org.springframework.expression.EvaluationContext; @@ -279,6 +285,33 @@ public class ExtensionAwareEvaluationContextProviderUnitTests { assertThat(evaluateExpression("methodWithVarArgs('one', 'two')")).isEqualTo("varargs"); } + @Test // DATACMNS-1534 + public void contextProviderShouldLazilyLookUpExtensions() { + + ListableBeanFactory beanFactory = Mockito.mock(ListableBeanFactory.class); + + ExtensionAwareEvaluationContextProvider contextProvider = new ExtensionAwareEvaluationContextProvider(beanFactory); + + verify(beanFactory, never()).getBeansOfType(eq(EvaluationContextExtension.class), anyBoolean(), anyBoolean()); + + contextProvider.getEvaluationContext(null); + + verify(beanFactory).getBeansOfType(eq(EvaluationContextExtension.class), anyBoolean(), anyBoolean()); + } + + @Test // DATACMNS-1534 + public void contextProviderShouldLookupExtensionsOnlyOnce() { + + ListableBeanFactory beanFactory = Mockito.mock(ListableBeanFactory.class); + + ExtensionAwareEvaluationContextProvider contextProvider = new ExtensionAwareEvaluationContextProvider(beanFactory); + + contextProvider.getEvaluationContext(null); + contextProvider.getEvaluationContext(null); + + verify(beanFactory).getBeansOfType(eq(EvaluationContextExtension.class), anyBoolean(), anyBoolean()); + } + private static ExtensionAwareQueryMethodEvaluationContextProvider createContextProviderWithOverloads() { return new ExtensionAwareQueryMethodEvaluationContextProvider(Collections.singletonList( //