SpEL supports record-style accessor methods as well
Closes gh-26029
This commit is contained in:
parent
412aa06d86
commit
079ca80854
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
|
@ -118,7 +118,7 @@ public final class Property {
|
|||
}
|
||||
|
||||
|
||||
// package private
|
||||
// Package private
|
||||
|
||||
MethodParameter getMethodParameter() {
|
||||
return this.methodParameter;
|
||||
|
|
@ -132,7 +132,7 @@ public final class Property {
|
|||
}
|
||||
|
||||
|
||||
// internal helpers
|
||||
// Internal helpers
|
||||
|
||||
private String resolveName() {
|
||||
if (this.readMethod != null) {
|
||||
|
|
@ -142,10 +142,13 @@ public final class Property {
|
|||
}
|
||||
else {
|
||||
index = this.readMethod.getName().indexOf("is");
|
||||
if (index == -1) {
|
||||
throw new IllegalArgumentException("Not a getter method");
|
||||
if (index != -1) {
|
||||
index += 2;
|
||||
}
|
||||
else {
|
||||
// Record-style plain accessor method, e.g. name()
|
||||
index = 0;
|
||||
}
|
||||
index += 2;
|
||||
}
|
||||
return StringUtils.uncapitalize(this.readMethod.getName().substring(index));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -395,6 +395,11 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
|||
if (method == null) {
|
||||
method = findMethodForProperty(getPropertyMethodSuffixes(propertyName),
|
||||
"is", clazz, mustBeStatic, 0, BOOLEAN_TYPES);
|
||||
if (method == null) {
|
||||
// Record-style plain accessor method, e.g. name()
|
||||
method = findMethodForProperty(new String[] {propertyName},
|
||||
"", clazz, mustBeStatic, 0, ANY_TYPES);
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
|
@ -683,12 +688,11 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
|||
return true;
|
||||
}
|
||||
getterName = "is" + StringUtils.capitalize(name);
|
||||
return getterName.equals(method.getName());
|
||||
}
|
||||
else {
|
||||
Field field = (Field) this.member;
|
||||
return field.getName().equals(name);
|
||||
if (getterName.equals(method.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return this.member.getName().equals(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
|
|
@ -36,6 +36,7 @@ import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
|||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.testresources.Inventor;
|
||||
import org.springframework.expression.spel.testresources.Person;
|
||||
import org.springframework.expression.spel.testresources.RecordPerson;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
|
@ -191,6 +192,20 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
|||
parser.parseExpression("name='p3'").getValue(context, target));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyReadOnlyWithRecordStyle() {
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
|
||||
Expression expr = parser.parseExpression("name");
|
||||
RecordPerson target1 = new RecordPerson("p1");
|
||||
assertThat(expr.getValue(context, target1)).isEqualTo("p1");
|
||||
RecordPerson target2 = new RecordPerson("p2");
|
||||
assertThat(expr.getValue(context, target2)).isEqualTo("p2");
|
||||
|
||||
assertThatExceptionOfType(SpelEvaluationException.class).isThrownBy(() ->
|
||||
parser.parseExpression("name='p3'").getValue(context, target2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyReadWrite() {
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
|
||||
|
|
|
|||
|
|
@ -4180,6 +4180,13 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertThat(expression.getValue(tc)).isEqualTo("value4");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value4");
|
||||
|
||||
// record-style accessor
|
||||
expression = parser.parseExpression("strawberry");
|
||||
assertCantCompile(expression);
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value5");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value5");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -4553,23 +4560,9 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
Object v = expression.getValue(ctx,holder);
|
||||
assertThat(v).isEqualTo("abc");
|
||||
|
||||
// // time it interpreted
|
||||
// long stime = System.currentTimeMillis();
|
||||
// for (int i = 0; i < 100000; i++) {
|
||||
// v = expression.getValue(ctx,holder);
|
||||
// }
|
||||
// System.out.println((System.currentTimeMillis() - stime));
|
||||
|
||||
assertCanCompile(expression);
|
||||
v = expression.getValue(ctx,holder);
|
||||
assertThat(v).isEqualTo("abc");
|
||||
|
||||
// // time it compiled
|
||||
// stime = System.currentTimeMillis();
|
||||
// for (int i = 0; i < 100000; i++) {
|
||||
// v = expression.getValue(ctx,holder);
|
||||
// }
|
||||
// System.out.println((System.currentTimeMillis() - stime));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -4985,13 +4978,12 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertThat(fast.compileExpression()).isTrue();
|
||||
r.setValue2(null);
|
||||
// try the numbers 0,1,2,null
|
||||
for (int i=0;i<4;i++) {
|
||||
r.setValue(i<3?i:null);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
r.setValue(i < 3 ? i : null);
|
||||
boolean slowResult = (Boolean)slow.getValue(ctx);
|
||||
boolean fastResult = (Boolean)fast.getValue(ctx);
|
||||
// System.out.println("Trying "+expressionText+" with value="+r.getValue()+" result is "+slowResult);
|
||||
assertThat(fastResult).as(" Differing results: expression="+expressionText+
|
||||
" value="+r.getValue()+" slow="+slowResult+" fast="+fastResult).isEqualTo(slowResult);
|
||||
assertThat(fastResult).as("Differing results: expression=" + expressionText +
|
||||
" value=" + r.getValue() + " slow=" + slowResult + " fast="+fastResult).isEqualTo(slowResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5002,13 +4994,12 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
assertThat(fast.compileExpression()).isTrue();
|
||||
Reg r = (Reg)ctx.getRootObject().getValue();
|
||||
// try the numbers 0,1,2,null
|
||||
for (int i=0;i<4;i++) {
|
||||
r.setValue(i<3?i:null);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
r.setValue(i < 3 ? i : null);
|
||||
boolean slowResult = (Boolean)slow.getValue(ctx);
|
||||
boolean fastResult = (Boolean)fast.getValue(ctx);
|
||||
// System.out.println("Trying "+expressionText+" with value="+r.getValue()+" result is "+slowResult);
|
||||
assertThat(fastResult).as(" Differing results: expression="+expressionText+
|
||||
" value="+r.getValue()+" slow="+slowResult+" fast="+fastResult).isEqualTo(slowResult);
|
||||
assertThat(fastResult).as("Differing results: expression=" + expressionText +
|
||||
" value=" + r.getValue() + " slow=" + slowResult + " fast="+fastResult).isEqualTo(slowResult);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5839,7 +5830,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
|
||||
public String orange = "value1";
|
||||
public static String apple = "value2";
|
||||
|
||||
public long peach = 34L;
|
||||
|
||||
public String getBanana() {
|
||||
|
|
@ -5849,6 +5839,10 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||
public static String getPlum() {
|
||||
return "value4";
|
||||
}
|
||||
|
||||
public String strawberry() {
|
||||
return "value5";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2002-2020 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel.testresources;
|
||||
|
||||
public class RecordPerson {
|
||||
|
||||
private String name;
|
||||
|
||||
private Company company;
|
||||
|
||||
public RecordPerson(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public RecordPerson(String name, Company company) {
|
||||
this.name = name;
|
||||
this.company = company;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Company company() {
|
||||
return company;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue