diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java b/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java index 0b8fb34abc0c..d41967a44f0a 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java @@ -149,7 +149,7 @@ public boolean canRead(EvaluationContext context, @Nullable Object target, Strin if (method != null) { // Treat it like a property... // The readerCache will only contain gettable properties (let's not worry about setters for now). - Property property = new Property(type, method, null); + Property property = new Property(type, method, null, name); TypeDescriptor typeDescriptor = new TypeDescriptor(property); Method methodToInvoke = ClassUtils.getPubliclyAccessibleMethodIfPossible(method, type); this.readerCache.put(cacheKey, new InvokerPair(methodToInvoke, typeDescriptor)); @@ -193,7 +193,7 @@ public TypedValue read(EvaluationContext context, @Nullable Object target, Strin if (method != null) { // Treat it like a property... // The readerCache will only contain gettable properties (let's not worry about setters for now). - Property property = new Property(type, method, null); + Property property = new Property(type, method, null, name); TypeDescriptor typeDescriptor = new TypeDescriptor(property); methodToInvoke = ClassUtils.getPubliclyAccessibleMethodIfPossible(method, type); invoker = new InvokerPair(methodToInvoke, typeDescriptor); @@ -251,7 +251,7 @@ public boolean canWrite(EvaluationContext context, @Nullable Object target, Stri Method method = findSetterForProperty(name, type, target); if (method != null) { // Treat it like a property - Property property = new Property(type, null, method); + Property property = new Property(type, null, method, name); TypeDescriptor typeDescriptor = new TypeDescriptor(property); method = ClassUtils.getPubliclyAccessibleMethodIfPossible(method, type); this.writerCache.put(cacheKey, method); diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java index 2209f56cd095..1c31dcbd4efa 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/PropertyAccessTests.java @@ -312,6 +312,21 @@ void propertyAccessWithArrayIndexOutOfBounds() { .extracting(SpelEvaluationException::getMessageCode).isEqualTo(SpelMessage.ARRAY_INDEX_OUT_OF_BOUNDS); } + @Test + void propertyAccessorUtilizesKnownPropertyName() { + StandardEvaluationContext context = new StandardEvaluationContext(new Inventor("Nikola Tesla")); + Expression expression = parser.parseExpression("name"); + + // This triggers ReflectivePropertyAccessor getter resolution and caching (reads) + Object value = expression.getValue(context); + assertThat(value).isEqualTo("Nikola Tesla"); + + // This triggers ReflectivePropertyAccessor setter resolution and caching (writes) + assertThat(expression.isWritable(context)).isTrue(); + expression.setValue(context, "New Name"); + assertThat(expression.getValue(context)).isEqualTo("New Name"); + } + private ThrowableTypeAssert assertThatSpelEvaluationException() { return assertThatExceptionOfType(SpelEvaluationException.class);