Skip to content

Commit de9bedc

Browse files
committed
Reuse parsed expression instead of reparsing it on every invocation.
Signed-off-by: Dominique Villard <[email protected]>
1 parent d49b37a commit de9bedc

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

spring-boot-project/spring-boot-observation/src/main/java/org/springframework/boot/observation/autoconfigure/SpelValueExpressionResolver.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616

1717
package org.springframework.boot.observation.autoconfigure;
1818

19+
import java.util.Map;
20+
import java.util.concurrent.ConcurrentHashMap;
21+
1922
import io.micrometer.common.annotation.ValueExpressionResolver;
2023

2124
import org.springframework.expression.Expression;
22-
import org.springframework.expression.ExpressionParser;
2325
import org.springframework.expression.spel.standard.SpelExpressionParser;
2426
import org.springframework.expression.spel.support.SimpleEvaluationContext;
2527

@@ -30,17 +32,23 @@
3032
*/
3133
class SpelValueExpressionResolver implements ValueExpressionResolver {
3234

35+
private final Map<String, Expression> expressionMap = new ConcurrentHashMap<>();
36+
3337
@Override
3438
public String resolve(String expression, Object parameter) {
3539
try {
3640
SimpleEvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
37-
ExpressionParser expressionParser = new SpelExpressionParser();
38-
Expression expressionToEvaluate = expressionParser.parseExpression(expression);
39-
return expressionToEvaluate.getValue(context, parameter, String.class);
41+
Expression parsedExpression = this.expressionMap.computeIfAbsent(expression,
42+
SpelValueExpressionResolver::parseExpression);
43+
return parsedExpression.getValue(context, parameter, String.class);
4044
}
4145
catch (Exception ex) {
4246
throw new IllegalStateException("Unable to evaluate SpEL expression '%s'".formatted(expression), ex);
4347
}
4448
}
4549

50+
private static Expression parseExpression(String expression) {
51+
return new SpelExpressionParser().parseExpression(expression);
52+
}
53+
4654
}

spring-boot-project/spring-boot-observation/src/test/java/org/springframework/boot/observation/autoconfigure/SpelValueExpressionResolverTests.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
import org.junit.jupiter.api.Test;
2222

23+
import org.springframework.test.util.ReflectionTestUtils;
24+
2325
import static org.assertj.core.api.Assertions.assertThat;
2426
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
2527

@@ -44,6 +46,19 @@ void checkInvalidExpression() {
4446
assertThatIllegalStateException().isThrownBy(() -> this.resolver.resolve("['bar'].first", value));
4547
}
4648

49+
@Test
50+
void checkParserReuse() {
51+
var map = (Map<?, ?>) ReflectionTestUtils.getField(this.resolver, "expressionMap");
52+
53+
this.resolver.resolve("length", "foo");
54+
this.resolver.resolve("length", "bar");
55+
56+
assertThat(map).hasSize(1);
57+
58+
this.resolver.resolve("isEmpty", "foo");
59+
assertThat(map).hasSize(2);
60+
}
61+
4762
record Pair(int first, int second) {
4863

4964
static Pair of(int first, int second) {

0 commit comments

Comments
 (0)