PropertyOrFieldReference checks cached PropertyAccessor against current EvaluationContext
Issue: SPR-15769
This commit is contained in:
parent
57f961e36b
commit
bcf9f21ecc
|
@ -172,14 +172,16 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||||
|
|
||||||
PropertyAccessor accessorToUse = this.cachedReadAccessor;
|
PropertyAccessor accessorToUse = this.cachedReadAccessor;
|
||||||
if (accessorToUse != null) {
|
if (accessorToUse != null) {
|
||||||
try {
|
if (evalContext.getPropertyAccessors().contains(accessorToUse)) {
|
||||||
return accessorToUse.read(evalContext, contextObject.getValue(), name);
|
try {
|
||||||
}
|
return accessorToUse.read(evalContext, contextObject.getValue(), name);
|
||||||
catch (Exception ex) {
|
}
|
||||||
// This is OK - it may have gone stale due to a class change,
|
catch (Exception ex) {
|
||||||
// let's try to get a new one and call it before giving up...
|
// This is OK - it may have gone stale due to a class change,
|
||||||
this.cachedReadAccessor = null;
|
// let's try to get a new one and call it before giving up...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this.cachedReadAccessor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PropertyAccessor> accessorsToTry =
|
List<PropertyAccessor> accessorsToTry =
|
||||||
|
@ -225,15 +227,17 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
||||||
|
|
||||||
PropertyAccessor accessorToUse = this.cachedWriteAccessor;
|
PropertyAccessor accessorToUse = this.cachedWriteAccessor;
|
||||||
if (accessorToUse != null) {
|
if (accessorToUse != null) {
|
||||||
try {
|
if (evalContext.getPropertyAccessors().contains(accessorToUse)) {
|
||||||
accessorToUse.write(evalContext, contextObject.getValue(), name, newValue);
|
try {
|
||||||
return;
|
accessorToUse.write(evalContext, contextObject.getValue(), name, newValue);
|
||||||
}
|
return;
|
||||||
catch (Exception ex) {
|
}
|
||||||
// This is OK - it may have gone stale due to a class change,
|
catch (Exception ex) {
|
||||||
// let's try to get a new one and call it before giving up...
|
// This is OK - it may have gone stale due to a class change,
|
||||||
this.cachedWriteAccessor = null;
|
// let's try to get a new one and call it before giving up...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this.cachedWriteAccessor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PropertyAccessor> accessorsToTry =
|
List<PropertyAccessor> accessorsToTry =
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2017 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +17,9 @@
|
||||||
package org.springframework.expression.spel;
|
package org.springframework.expression.spel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -34,12 +36,11 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
///CLOVER:OFF
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests accessing of properties.
|
* Tests accessing of properties.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Juergen Hoeller
|
||||||
*/
|
*/
|
||||||
public class PropertyAccessTests extends AbstractExpressionTests {
|
public class PropertyAccessTests extends AbstractExpressionTests {
|
||||||
|
|
||||||
|
@ -167,6 +168,20 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||||
assertEquals(value, "java.lang.String");
|
assertEquals(value, "java.lang.String");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldAlwaysUsePropertyAccessorFromEvaluationContext() {
|
||||||
|
SpelExpressionParser parser = new SpelExpressionParser();
|
||||||
|
Expression expression = parser.parseExpression("name");
|
||||||
|
|
||||||
|
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||||
|
context.addPropertyAccessor(new ConfigurablePropertyAccessor(Collections.singletonMap("name", "Ollie")));
|
||||||
|
assertEquals("Ollie", expression.getValue(context));
|
||||||
|
|
||||||
|
context = new StandardEvaluationContext();
|
||||||
|
context.addPropertyAccessor(new ConfigurablePropertyAccessor(Collections.singletonMap("name", "Jens")));
|
||||||
|
assertEquals("Jens", expression.getValue(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// This can resolve the property 'flibbles' on any String (very useful...)
|
// This can resolve the property 'flibbles' on any String (very useful...)
|
||||||
private static class StringyPropertyAccessor implements PropertyAccessor {
|
private static class StringyPropertyAccessor implements PropertyAccessor {
|
||||||
|
@ -216,4 +231,38 @@ public class PropertyAccessTests extends AbstractExpressionTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class ConfigurablePropertyAccessor implements PropertyAccessor {
|
||||||
|
|
||||||
|
private final Map<String, Object> values;
|
||||||
|
|
||||||
|
public ConfigurablePropertyAccessor(Map<String, Object> values) {
|
||||||
|
this.values = values;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?>[] getSpecificTargetClasses() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRead(EvaluationContext context, Object target, String name) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypedValue read(EvaluationContext context, Object target, String name) {
|
||||||
|
return new TypedValue(this.values.get(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canWrite(EvaluationContext context, Object target, String name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(EvaluationContext context, Object target, String name, Object newValue) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue