Browse Source

DATACMNS-1534 - Cache BeanFactory lookup for EvaluationContextExtension.

We now cache the BeanFactory lookup for EvaluationContextExtension within the ExtensionAwareEvalutationContextProvider to avoid (expensive) repeated context scans when creating the actual EvaluationContext.

Original pull request: #395.
pull/396/head
Christoph Strobl 7 years ago committed by Oliver Drotbohm
parent
commit
d6bb21d24f
  1. 9
      src/main/java/org/springframework/data/repository/query/ExtensionAwareQueryMethodEvaluationContextProvider.java
  2. 8
      src/main/java/org/springframework/data/spel/ExtensionAwareEvaluationContextProvider.java
  3. 33
      src/test/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProviderUnitTests.java

9
src/main/java/org/springframework/data/repository/query/ExtensionAwareQueryMethodEvaluationContextProvider.java

@ -30,7 +30,6 @@ import org.aopalliance.intercept.MethodInvocation; @@ -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; @@ -52,7 +51,7 @@ import org.springframework.util.StringUtils;
*/
public class ExtensionAwareQueryMethodEvaluationContextProvider implements QueryMethodEvaluationContextProvider {
private final Lazy<org.springframework.data.spel.ExtensionAwareEvaluationContextProvider> delegate;
private final ExtensionAwareEvaluationContextProvider delegate;
/**
* Creates a new {@link ExtensionAwareQueryMethodEvaluationContextProvider}.
@ -64,7 +63,7 @@ public class ExtensionAwareQueryMethodEvaluationContextProvider implements Query @@ -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 @@ -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 @@ -87,7 +86,7 @@ public class ExtensionAwareQueryMethodEvaluationContextProvider implements Query
@Override
public <T extends Parameters<?, ?>> EvaluationContext getEvaluationContext(T parameters, Object[] parameterValues) {
StandardEvaluationContext evaluationContext = delegate.get().getEvaluationContext(parameterValues);
StandardEvaluationContext evaluationContext = delegate.getEvaluationContext(parameterValues);
evaluationContext.setVariables(collectVariables(parameters, parameterValues));

8
src/main/java/org/springframework/data/spel/ExtensionAwareEvaluationContextProvider.java

@ -25,7 +25,6 @@ import java.util.List; @@ -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 @@ -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 @@ -66,7 +66,7 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex
private final Map<Class<?>, EvaluationContextExtensionInformation> extensionInformationCache = new ConcurrentHashMap<>();
private final Supplier<? extends Collection<? extends EvaluationContextExtension>> extensions;
private final Lazy<? extends Collection<? extends EvaluationContextExtension>> extensions;
private ListableBeanFactory beanFactory;
ExtensionAwareEvaluationContextProvider() {
@ -81,7 +81,7 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex @@ -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 @@ -92,7 +92,7 @@ public class ExtensionAwareEvaluationContextProvider implements EvaluationContex
* @param extensions must not be {@literal null}.
*/
public ExtensionAwareEvaluationContextProvider(Collection<? extends EvaluationContextExtension> extensions) {
this(() -> extensions);
this(Lazy.of(extensions));
}
/* (non-Javadoc)

33
src/test/java/org/springframework/data/repository/query/ExtensionAwareEvaluationContextProviderUnitTests.java

@ -16,6 +16,9 @@ @@ -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; @@ -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 { @@ -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( //

Loading…
Cancel
Save