SpEL support for static finals on interfaces

Update ReflectivePropertyAccessor to search for fields on super classes
and implemented interfaces.

Although the javadoc Class.getFields() implies that all public fields
of class should be returned SpelReproTests demonstrates that this is
not always the case.

Issue: SPR-10125
This commit is contained in:
Phillip Webb 2013-01-14 15:49:38 -08:00
parent bff36fb145
commit ad91fa63fa
2 changed files with 35 additions and 0 deletions

View File

@ -383,6 +383,18 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return field;
}
}
if(clazz.getSuperclass() != null) {
Field field = findField(name, clazz.getSuperclass(), mustBeStatic);
if(field != null) {
return field;
}
}
for (Class<?> implementedInterface : clazz.getInterfaces()) {
Field field = findField(name, implementedInterface, mustBeStatic);
if(field != null) {
return field;
}
}
return null;
}

View File

@ -16,8 +16,10 @@
package org.springframework.expression.spel;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@ -1720,6 +1722,15 @@ public class SpelReproTests extends ExpressionTestCase {
new SpelExpressionParser().parseExpression(expression);
}
@Test
public void SPR_10125() throws Exception {
StandardEvaluationContext context = new StandardEvaluationContext();
String fromInterface = parser.parseExpression("T("+StaticFinalImpl1.class.getName()+").VALUE").getValue(context, String.class);
assertThat(fromInterface, is("interfaceValue"));
String fromClass = parser.parseExpression("T("+StaticFinalImpl2.class.getName()+").VALUE").getValue(context, String.class);
assertThat(fromClass, is("interfaceValue"));
}
public static class BooleanHolder {
private Boolean simpleProperty = true;
@ -1768,4 +1779,16 @@ public class SpelReproTests extends ExpressionTestCase {
}
public static interface StaticFinal {
public static final String VALUE = "interfaceValue";
}
public abstract static class AbstractStaticFinal implements StaticFinal {
}
public static class StaticFinalImpl1 extends AbstractStaticFinal implements StaticFinal {
}
public static class StaticFinalImpl2 extends AbstractStaticFinal {
}
}