diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java index 019faf2836..33d1f510b1 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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. @@ -90,7 +90,7 @@ public class ReflectiveMethodResolver implements MethodResolver { try { TypeConverter typeConverter = context.getTypeConverter(); Class type = (targetObject instanceof Class ? (Class) targetObject : targetObject.getClass()); - Method[] methods = type.getMethods(); + Method[] methods = getMethods(type); // If a filter is registered for this type, call it MethodFilter filter = (this.filters != null ? this.filters.get(type) : null); @@ -197,4 +197,16 @@ public class ReflectiveMethodResolver implements MethodResolver { } } + /** + * Return the set of methods for this type. The default implementation returns the + * result of Class#getMethods for the given {@code type}, but subclasses may override + * in order to alter the results, e.g. specifying static methods declared elsewhere. + * + * @param type the class for which to return the methods + * @since 3.1.1 + */ + protected Method[] getMethods(Class type) { + return type.getMethods(); + } + } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java index e28f9dd3a1..0fa4d1fbd1 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java @@ -17,8 +17,10 @@ package org.springframework.expression.spel; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; @@ -38,6 +40,7 @@ import org.springframework.expression.EvaluationException; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.MethodExecutor; +import org.springframework.expression.MethodResolver; import org.springframework.expression.ParserContext; import org.springframework.expression.PropertyAccessor; import org.springframework.expression.TypedValue; @@ -1137,6 +1140,41 @@ public class SpringEL300Tests extends ExpressionTestCase { public Map getFourthContext() {return fourthContext;} } + /** + * Test the ability to subclass the ReflectiveMethodResolver and change how it + * determines the set of methods for a type. + */ + @Test + public void testCustomStaticFunctions_SPR9038() { + try { + ExpressionParser parser = new SpelExpressionParser(); + StandardEvaluationContext context = new StandardEvaluationContext(); + List methodResolvers = new ArrayList(); + methodResolvers.add(new ReflectiveMethodResolver() { + @Override + protected Method[] getMethods(Class type) { + try { + return new Method[] { + Integer.class.getDeclaredMethod("parseInt", new Class[] { + String.class, Integer.TYPE }) }; + } catch (NoSuchMethodException e1) { + return new Method[0]; + } + } + }); + + context.setMethodResolvers(methodResolvers); + org.springframework.expression.Expression expression = + parser.parseExpression("parseInt('-FF', 16)"); + + Integer result = expression.getValue(context, "", Integer.class); + assertEquals("Equal assertion failed: ", -255, result.intValue()); + } catch (Exception e) { + e.printStackTrace(); + fail("Unexpected exception: "+e.toString()); + } + } + }