Skip to content

Commit 9b7f64a

Browse files
committed
Fix SpEL generated code for default method invocation
Closes gh-25706 (cherry picked from commit c368ce8)
1 parent 755721f commit 9b7f64a

File tree

3 files changed

+71
-6
lines changed

3 files changed

+71
-6
lines changed

spring-expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -351,8 +351,9 @@ public void generateCode(MethodVisitor mv, CodeFlow cf) {
351351
}
352352

353353
generateCodeForArguments(mv, cf, method, this.children);
354-
mv.visitMethodInsn((isStaticMethod ? INVOKESTATIC : INVOKEVIRTUAL), classDesc, method.getName(),
355-
CodeFlow.createSignatureDescriptor(method), method.getDeclaringClass().isInterface());
354+
mv.visitMethodInsn((isStaticMethod ? INVOKESTATIC : (method.isDefault() ? INVOKEINTERFACE : INVOKEVIRTUAL)),
355+
classDesc, method.getName(), CodeFlow.createSignatureDescriptor(method),
356+
method.getDeclaringClass().isInterface());
356357
cf.pushDescriptor(this.exitTypeDescriptor);
357358

358359
if (this.originalPrimitiveExitTypeDescriptor != null) {

spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5183,7 +5183,7 @@ private void assertGetValueFail(Expression expression) {
51835183
}
51845184
}
51855185

5186-
private void assertIsCompiled(Expression expression) {
5186+
public static void assertIsCompiled(Expression expression) {
51875187
try {
51885188
Field field = SpelExpression.class.getDeclaredField("compiledAst");
51895189
field.setAccessible(true);

spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelCompilerTests.java

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,23 @@
2222

2323
import org.springframework.core.Ordered;
2424
import org.springframework.expression.Expression;
25+
import org.springframework.expression.spel.SpelCompilationCoverageTests;
2526
import org.springframework.expression.spel.SpelCompilerMode;
2627
import org.springframework.expression.spel.SpelParserConfiguration;
28+
import org.springframework.expression.spel.support.StandardEvaluationContext;
2729

28-
import static org.junit.Assert.assertEquals;
30+
import static org.junit.Assert.*;
2931

3032
/**
3133
* Tests for the {@link SpelCompiler}.
3234
*
3335
* @author Sam Brannen
36+
* @author Andy Clement
3437
* @since 5.1.14
3538
*/
3639
public class SpelCompilerTests {
3740

38-
@Test // gh-24357
41+
@Test // gh-24357
3942
public void expressionCompilesWhenMethodComesFromPublicInterface() {
4043
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null);
4144
SpelExpressionParser parser = new SpelExpressionParser(config);
@@ -47,6 +50,31 @@ public void expressionCompilesWhenMethodComesFromPublicInterface() {
4750
IntStream.rangeClosed(1, 5).forEach(i -> assertEquals(42, expression.getValue(component)));
4851
}
4952

53+
@Test // gh-25706
54+
public void defaultMethodInvocation() {
55+
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null);
56+
SpelExpressionParser parser = new SpelExpressionParser(config);
57+
58+
StandardEvaluationContext context = new StandardEvaluationContext();
59+
Item item = new Item();
60+
context.setRootObject(item);
61+
62+
Expression expression = parser.parseExpression("#root.isEditable2()");
63+
assertFalse(SpelCompiler.compile(expression));
64+
assertEquals(false, expression.getValue(context));
65+
assertTrue(SpelCompiler.compile(expression));
66+
SpelCompilationCoverageTests.assertIsCompiled(expression);
67+
assertEquals(false, expression.getValue(context));
68+
69+
context.setVariable("user", new User());
70+
expression = parser.parseExpression("#root.isEditable(#user)");
71+
assertFalse(SpelCompiler.compile(expression));
72+
assertEquals(true, expression.getValue(context));
73+
assertTrue(SpelCompiler.compile(expression));
74+
SpelCompilationCoverageTests.assertIsCompiled(expression);
75+
assertEquals(true, expression.getValue(context));
76+
}
77+
5078

5179
static class OrderedComponent implements Ordered {
5280

@@ -56,4 +84,40 @@ public int getOrder() {
5684
}
5785
}
5886

87+
88+
public static class User {
89+
90+
boolean isAdmin() {
91+
return true;
92+
}
93+
}
94+
95+
96+
public static class Item implements Editable {
97+
98+
// some fields
99+
private String someField = "";
100+
101+
// some getters and setters
102+
103+
@Override
104+
public boolean hasSomeProperty() {
105+
return someField != null;
106+
}
107+
}
108+
109+
110+
public interface Editable {
111+
112+
default boolean isEditable(User user) {
113+
return user.isAdmin() && hasSomeProperty();
114+
}
115+
116+
default boolean isEditable2() {
117+
return false;
118+
}
119+
120+
boolean hasSomeProperty();
121+
}
122+
59123
}

0 commit comments

Comments
 (0)