Browse Source

Consider bridge methods in SpEL properties

Revert ReflectivePropertyAccessor changes from 107fafb and instead
consider all methods when resolving properties. Methods are now
sorted such that non-bridge methods are considered before bridge
methods.

Issue: SPR-10162
pull/215/head
Phillip Webb 13 years ago
parent
commit
fce7adc400
  1. 26
      spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java
  2. 23
      spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java

26
spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectivePropertyAccessor.java

@ -21,6 +21,8 @@ import java.lang.reflect.Field; @@ -21,6 +21,8 @@ import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -310,13 +312,13 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { @@ -310,13 +312,13 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
* Find a getter method for the specified property.
*/
protected Method findGetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
Method[] ms = clazz.getMethods();
Method[] ms = getSortedClassMethods(clazz);
String propertyMethodSuffix = getPropertyMethodSuffix(propertyName);
// Try "get*" method...
String getterName = "get" + propertyMethodSuffix;
for (Method method : ms) {
if (!method.isBridge() && method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
if (method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
return method;
}
@ -324,7 +326,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { @@ -324,7 +326,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
// Try "is*" method...
getterName = "is" + propertyMethodSuffix;
for (Method method : ms) {
if (!method.isBridge() && method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
if (method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
(boolean.class.equals(method.getReturnType()) || Boolean.class.equals(method.getReturnType())) &&
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
return method;
@ -337,10 +339,10 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { @@ -337,10 +339,10 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
* Find a setter method for the specified property.
*/
protected Method findSetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
Method[] methods = clazz.getMethods();
Method[] methods = getSortedClassMethods(clazz);
String setterName = "set" + getPropertyMethodSuffix(propertyName);
for (Method method : methods) {
if (!method.isBridge() && method.getName().equals(setterName) && method.getParameterTypes().length == 1 &&
if (method.getName().equals(setterName) && method.getParameterTypes().length == 1 &&
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
return method;
}
@ -348,6 +350,20 @@ public class ReflectivePropertyAccessor implements PropertyAccessor { @@ -348,6 +350,20 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
return null;
}
/**
* Returns class methods ordered with non bridge methods appearing higher.
*/
private Method[] getSortedClassMethods(Class<?> clazz) {
Method[] methods = clazz.getMethods();
Arrays.sort(methods, new Comparator<Method>() {
@Override
public int compare(Method o1, Method o2) {
return (o1.isBridge() == o2.isBridge()) ? 0 : (o1.isBridge() ? 1 : -1);
}
});
return methods;
}
protected String getPropertyMethodSuffix(String propertyName) {
if (propertyName.length() > 1 && Character.isUpperCase(propertyName.charAt(1))) {
return propertyName;

23
spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2013 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.
@ -56,6 +56,7 @@ import static org.junit.Assert.*; @@ -56,6 +56,7 @@ import static org.junit.Assert.*;
* @author Andy Clement
* @author Juergen Hoeller
* @author Clark Duplichien
* @author Phillip Webb
*/
public class SpelReproTests extends ExpressionTestCase {
@ -1656,6 +1657,15 @@ public class SpelReproTests extends ExpressionTestCase { @@ -1656,6 +1657,15 @@ public class SpelReproTests extends ExpressionTestCase {
assertEquals(Integer.class, value.getTypeDescriptor().getType());
}
@Test
public void SPR_10162_onlyBridgeMethodTest() throws Exception {
ReflectivePropertyAccessor accessor = new ReflectivePropertyAccessor();
StandardEvaluationContext context = new StandardEvaluationContext();
Object target = new OnlyBridgeMethod();
TypedValue value = accessor.read(context, target , "property");
assertEquals(Integer.class, value.getTypeDescriptor().getType());
}
@Test
public void SPR_10091_simpleTestValueType() {
ExpressionParser parser = new SpelExpressionParser();
@ -1722,4 +1732,15 @@ public class SpelReproTests extends ExpressionTestCase { @@ -1722,4 +1732,15 @@ public class SpelReproTests extends ExpressionTestCase {
}
}
static class PackagePrivateClassWithGetter {
public Integer getProperty() {
return null;
}
}
public static class OnlyBridgeMethod extends PackagePrivateClassWithGetter {
}
}

Loading…
Cancel
Save