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 97d87d50c3b..7b7ce34179a 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 @@ -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 { * 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 { // 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 { * 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 { 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() { + @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; diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java index e1122ab04f9..9cb0a582532 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java @@ -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.*; * @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 { 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 { } } + static class PackagePrivateClassWithGetter { + + public Integer getProperty() { + return null; + } + } + + public static class OnlyBridgeMethod extends PackagePrivateClassWithGetter { + + } + }