Share internal StandardExecutionContext delegates
This commit makes sure that the per-operation execution context for caching and event listening does not recreate the default internal delegates, but rather get initialized with a shared state. This reduces the number of instances created per operation execution, reducing the GC pressure as a result. This also makes sure that any cache, such as the one in StandardTypeLocator, is reused. Closes gh-31617
This commit is contained in:
@@ -31,9 +31,12 @@ import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.annotation.Caching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||
import org.springframework.context.expression.AnnotatedElementKey;
|
||||
import org.springframework.context.expression.BeanFactoryResolver;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -47,7 +50,10 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
*/
|
||||
public class ExpressionEvaluatorTests {
|
||||
|
||||
private final CacheOperationExpressionEvaluator eval = new CacheOperationExpressionEvaluator();
|
||||
private final StandardEvaluationContext originalEvaluationContext = new StandardEvaluationContext();
|
||||
|
||||
private final CacheOperationExpressionEvaluator eval = new CacheOperationExpressionEvaluator(
|
||||
new CacheEvaluationContextFactory(this.originalEvaluationContext));
|
||||
|
||||
private final AnnotationCacheOperationSource source = new AnnotationCacheOperationSource();
|
||||
|
||||
@@ -82,7 +88,7 @@ public class ExpressionEvaluatorTests {
|
||||
Collection<ConcurrentMapCache> caches = Collections.singleton(new ConcurrentMapCache("test"));
|
||||
|
||||
EvaluationContext evalCtx = this.eval.createEvaluationContext(caches, method, args,
|
||||
target, target.getClass(), method, CacheOperationExpressionEvaluator.NO_RESULT, null);
|
||||
target, target.getClass(), method, CacheOperationExpressionEvaluator.NO_RESULT);
|
||||
Collection<CacheOperation> ops = getOps("multipleCaching");
|
||||
|
||||
Iterator<CacheOperation> it = ops.iterator();
|
||||
@@ -140,14 +146,17 @@ public class ExpressionEvaluatorTests {
|
||||
return createEvaluationContext(result, null);
|
||||
}
|
||||
|
||||
private EvaluationContext createEvaluationContext(Object result, BeanFactory beanFactory) {
|
||||
private EvaluationContext createEvaluationContext(Object result, @Nullable BeanFactory beanFactory) {
|
||||
if (beanFactory != null) {
|
||||
this.originalEvaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
|
||||
}
|
||||
AnnotatedClass target = new AnnotatedClass();
|
||||
Method method = ReflectionUtils.findMethod(
|
||||
AnnotatedClass.class, "multipleCaching", Object.class, Object.class);
|
||||
Object[] args = new Object[] {new Object(), new Object()};
|
||||
Collection<ConcurrentMapCache> caches = Collections.singleton(new ConcurrentMapCache("test"));
|
||||
return this.eval.createEvaluationContext(
|
||||
caches, method, args, target, target.getClass(), method, result, beanFactory);
|
||||
caches, method, args, target, target.getClass(), method, result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.core.Ordered;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.ResolvableTypeProvider;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -322,7 +323,7 @@ public class ApplicationListenerMethodAdapterTests extends AbstractApplicationEv
|
||||
given(this.context.getBean("testBean")).willReturn(this.sampleEvents);
|
||||
ApplicationListenerMethodAdapter listener = new ApplicationListenerMethodAdapter(
|
||||
"testBean", GenericTestEvent.class, method);
|
||||
listener.init(this.context, new EventExpressionEvaluator());
|
||||
listener.init(this.context, new EventExpressionEvaluator(new StandardEvaluationContext()));
|
||||
GenericTestEvent<String> event = createGenericTestEvent("test");
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user