Re-use EvaluationContext in DefaultSubscriptionRegistry
Rather than create a new EvaluationContext instance per evaluation, we now create a statically shared instance, without the root object in it, and re-use it for all evalutations.
This commit is contained in:
parent
19293b9847
commit
e0de9126ed
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -26,7 +26,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ExpressionParser;
|
||||
|
@ -34,7 +33,7 @@ import org.springframework.expression.PropertyAccessor;
|
|||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
|
@ -65,6 +64,11 @@ public class DefaultSubscriptionRegistry extends AbstractSubscriptionRegistry {
|
|||
/** Default maximum number of entries for the destination cache: 1024 */
|
||||
public static final int DEFAULT_CACHE_LIMIT = 1024;
|
||||
|
||||
/** Static evaluation context to re-use */
|
||||
private static SimpleEvaluationContext evaluationContext = SimpleEvaluationContext.builder()
|
||||
.propertyAccessor(new SimpMessageHeaderPropertyAccessor()).build();
|
||||
|
||||
|
||||
|
||||
private PathMatcher pathMatcher = new AntPathMatcher();
|
||||
|
||||
|
@ -192,7 +196,6 @@ public class DefaultSubscriptionRegistry extends AbstractSubscriptionRegistry {
|
|||
if (!this.selectorHeaderInUse) {
|
||||
return allMatches;
|
||||
}
|
||||
EvaluationContext context = null;
|
||||
MultiValueMap<String, String> result = new LinkedMultiValueMap<>(allMatches.size());
|
||||
for (String sessionId : allMatches.keySet()) {
|
||||
for (String subId : allMatches.get(sessionId)) {
|
||||
|
@ -209,12 +212,8 @@ public class DefaultSubscriptionRegistry extends AbstractSubscriptionRegistry {
|
|||
result.add(sessionId, subId);
|
||||
continue;
|
||||
}
|
||||
if (context == null) {
|
||||
context = new StandardEvaluationContext(message);
|
||||
context.getPropertyAccessors().add(new SimpMessageHeaderPropertyAccessor());
|
||||
}
|
||||
try {
|
||||
if (Boolean.TRUE.equals(expression.getValue(context, Boolean.class))) {
|
||||
if (Boolean.TRUE.equals(expression.getValue(evaluationContext, message, Boolean.class))) {
|
||||
result.add(sessionId, subId);
|
||||
}
|
||||
}
|
||||
|
@ -533,7 +532,7 @@ public class DefaultSubscriptionRegistry extends AbstractSubscriptionRegistry {
|
|||
|
||||
@Override
|
||||
public Class<?>[] getSpecificTargetClasses() {
|
||||
return new Class<?>[] {MessageHeaders.class};
|
||||
return new Class<?>[] {Message.class, MessageHeaders.class};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -542,21 +541,29 @@ public class DefaultSubscriptionRegistry extends AbstractSubscriptionRegistry {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException {
|
||||
Assert.state(target instanceof MessageHeaders, "No MessageHeaders");
|
||||
MessageHeaders headers = (MessageHeaders) target;
|
||||
SimpMessageHeaderAccessor accessor =
|
||||
MessageHeaderAccessor.getAccessor(headers, SimpMessageHeaderAccessor.class);
|
||||
Assert.state(accessor != null, "No SimpMessageHeaderAccessor");
|
||||
public TypedValue read(EvaluationContext context, @Nullable Object target, String name) {
|
||||
Object value;
|
||||
if ("destination".equalsIgnoreCase(name)) {
|
||||
value = accessor.getDestination();
|
||||
if (target instanceof Message) {
|
||||
value = name.equals("headers") ? ((Message) target).getHeaders() : null;
|
||||
}
|
||||
else if (target instanceof MessageHeaders) {
|
||||
MessageHeaders headers = (MessageHeaders) target;
|
||||
SimpMessageHeaderAccessor accessor =
|
||||
MessageHeaderAccessor.getAccessor(headers, SimpMessageHeaderAccessor.class);
|
||||
Assert.state(accessor != null, "No SimpMessageHeaderAccessor");
|
||||
if ("destination".equalsIgnoreCase(name)) {
|
||||
value = accessor.getDestination();
|
||||
}
|
||||
else {
|
||||
value = accessor.getFirstNativeHeader(name);
|
||||
if (value == null) {
|
||||
value = headers.get(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
value = accessor.getFirstNativeHeader(name);
|
||||
if (value == null) {
|
||||
value = headers.get(name);
|
||||
}
|
||||
// Should never happen...
|
||||
throw new IllegalStateException("Expected Message or MessageHeaders.");
|
||||
}
|
||||
return new TypedValue(value);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue