提交 7123e4f8 编写于 作者: J Juergen Hoeller

expression parser uses context's ConversionService by default

上级 efaf76b4
...@@ -23,11 +23,14 @@ import org.springframework.beans.BeansException; ...@@ -23,11 +23,14 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanExpressionException; import org.springframework.beans.factory.BeanExpressionException;
import org.springframework.beans.factory.config.BeanExpressionContext; import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver; import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.core.convert.ConversionService;
import org.springframework.expression.Expression; import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser; import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext; import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.StandardTypeConverter;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
...@@ -96,7 +99,7 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver { ...@@ -96,7 +99,7 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
/** /**
* Specify the EL parser to use for expression parsing. * Specify the EL parser to use for expression parsing.
* <p>Default is a {@link org.springframework.expression.spel.SpelExpressionParser}, * <p>Default is a {@link org.springframework.expression.spel.standard.SpelExpressionParser},
* compatible with standard Unified EL style expression syntax. * compatible with standard Unified EL style expression syntax.
*/ */
public void setExpressionParser(ExpressionParser expressionParser) { public void setExpressionParser(ExpressionParser expressionParser) {
...@@ -119,6 +122,11 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver { ...@@ -119,6 +122,11 @@ public class StandardBeanExpressionResolver implements BeanExpressionResolver {
sec.addPropertyAccessor(new BeanExpressionContextAccessor()); sec.addPropertyAccessor(new BeanExpressionContextAccessor());
sec.addPropertyAccessor(new BeanFactoryAccessor()); sec.addPropertyAccessor(new BeanFactoryAccessor());
sec.addPropertyAccessor(new MapAccessor()); sec.addPropertyAccessor(new MapAccessor());
sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
if (conversionService != null) {
sec.setTypeConverter(new StandardTypeConverter(conversionService));
}
customizeEvaluationContext(sec); customizeEvaluationContext(sec);
this.evaluationCache.put(evalContext, sec); this.evaluationCache.put(evalContext, sec);
} }
......
...@@ -21,11 +21,11 @@ import java.util.List; ...@@ -21,11 +21,11 @@ import java.util.List;
/** /**
* Expressions are executed in an evaluation context. It is in this context that references * Expressions are executed in an evaluation context. It is in this context that references
* are resolved when encountered during expression evaluation. * are resolved when encountered during expression evaluation.
* *
* There is a default implementation of the EvaluationContext, * <p>There is a default implementation of the EvaluationContext,
* {@link org.springframework.expression.spel.support.StandardEvaluationContext} * {@link org.springframework.expression.spel.support.StandardEvaluationContext}
* that can be extended, rather than having to implement everything. * that can be extended, rather than having to implement everything.
* *
* @author Andy Clement * @author Andy Clement
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 3.0 * @since 3.0
...@@ -36,27 +36,6 @@ public interface EvaluationContext { ...@@ -36,27 +36,6 @@ public interface EvaluationContext {
* @return the root context object against which unqualified properties/methods/etc should be resolved * @return the root context object against which unqualified properties/methods/etc should be resolved
*/ */
TypedValue getRootObject(); TypedValue getRootObject();
/**
* @param rootObject the root object against which unqualified properties/methods/etc should be resolved
*/
void setRootObject(Object object);
/**
* Set a named variable within this execution context to a specified value.
* @param name variable to set
* @param value value to be placed in the variable
*/
void setVariable(String name, Object value);
/**
* Look up a named variable within this execution context.
* @param name variable to lookup
* @return the value of the variable
*/
Object lookupVariable(String name);
/** /**
* @return a list of resolvers that will be asked in turn to locate a constructor * @return a list of resolvers that will be asked in turn to locate a constructor
...@@ -79,14 +58,14 @@ public interface EvaluationContext { ...@@ -79,14 +58,14 @@ public interface EvaluationContext {
TypeLocator getTypeLocator(); TypeLocator getTypeLocator();
/** /**
* @return a type comparator for comparing pairs of objects for equality. * @return a type converter that can convert (or coerce) a value from one type to another.
*/ */
TypeComparator getTypeComparator(); TypeConverter getTypeConverter();
/** /**
* @return a type converter that can convert (or coerce) a value from one type to another. * @return a type comparator for comparing pairs of objects for equality.
*/ */
TypeConverter getTypeConverter(); TypeComparator getTypeComparator();
/** /**
* @return an operator overloader that may support mathematical operations between more than the standard set of * @return an operator overloader that may support mathematical operations between more than the standard set of
...@@ -94,4 +73,18 @@ public interface EvaluationContext { ...@@ -94,4 +73,18 @@ public interface EvaluationContext {
*/ */
OperatorOverloader getOperatorOverloader(); OperatorOverloader getOperatorOverloader();
/**
* Set a named variable within this evaluation context to a specified value.
* @param name variable to set
* @param value value to be placed in the variable
*/
void setVariable(String name, Object value);
/**
* Look up a named variable within this evaluation context.
* @param name variable to lookup
* @return the value of the variable
*/
Object lookupVariable(String name);
} }
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.expression.spel; package org.springframework.expression.spel;
import java.util.HashMap; import java.util.HashMap;
...@@ -36,7 +37,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParserConfigur ...@@ -36,7 +37,7 @@ import org.springframework.expression.spel.standard.SpelExpressionParserConfigur
* communicate state. This is in contrast to the EvaluationContext, which is shared amongst expression evaluations, and * communicate state. This is in contrast to the EvaluationContext, which is shared amongst expression evaluations, and
* any changes to it will be seen by other expressions or any code that chooses to ask questions of the context. * any changes to it will be seen by other expressions or any code that chooses to ask questions of the context.
* *
* It also acts as a place for to define common utility routines that the various Ast nodes might need. * <p>It also acts as a place for to define common utility routines that the various Ast nodes might need.
* *
* @author Andy Clement * @author Andy Clement
* @since 3.0 * @since 3.0
...@@ -75,7 +76,8 @@ public class ExpressionState { ...@@ -75,7 +76,8 @@ public class ExpressionState {
TypedValue rootObject = this.relatedContext.getRootObject(); TypedValue rootObject = this.relatedContext.getRootObject();
if (rootObject == null) { if (rootObject == null) {
return TypedValue.NULL_TYPED_VALUE; return TypedValue.NULL_TYPED_VALUE;
} else { }
else {
return rootObject; return rootObject;
} }
} }
...@@ -94,7 +96,8 @@ public class ExpressionState { ...@@ -94,7 +96,8 @@ public class ExpressionState {
TypedValue root = this.relatedContext.getRootObject(); TypedValue root = this.relatedContext.getRootObject();
if (root == null) { if (root == null) {
return TypedValue.NULL_TYPED_VALUE; return TypedValue.NULL_TYPED_VALUE;
} else { }
else {
return root; return root;
} }
} }
...@@ -105,10 +108,11 @@ public class ExpressionState { ...@@ -105,10 +108,11 @@ public class ExpressionState {
public TypedValue lookupVariable(String name) { public TypedValue lookupVariable(String name) {
Object value = this.relatedContext.lookupVariable(name); Object value = this.relatedContext.lookupVariable(name);
if (value==null) { if (value == null) {
return TypedValue.NULL_TYPED_VALUE; return TypedValue.NULL_TYPED_VALUE;
} else { }
return new TypedValue(value,TypeDescriptor.forObject(value)); else {
return new TypedValue(value, TypeDescriptor.forObject(value));
} }
} }
......
...@@ -47,8 +47,6 @@ public class StandardEvaluationContext implements EvaluationContext { ...@@ -47,8 +47,6 @@ public class StandardEvaluationContext implements EvaluationContext {
private TypedValue rootObject; private TypedValue rootObject;
private final Map<String, Object> variables = new HashMap<String, Object>();
private final List<ConstructorResolver> constructorResolvers = new ArrayList<ConstructorResolver>(); private final List<ConstructorResolver> constructorResolvers = new ArrayList<ConstructorResolver>();
private final List<MethodResolver> methodResolvers = new ArrayList<MethodResolver>(); private final List<MethodResolver> methodResolvers = new ArrayList<MethodResolver>();
...@@ -57,12 +55,15 @@ public class StandardEvaluationContext implements EvaluationContext { ...@@ -57,12 +55,15 @@ public class StandardEvaluationContext implements EvaluationContext {
private TypeLocator typeLocator = new StandardTypeLocator(); private TypeLocator typeLocator = new StandardTypeLocator();
private TypeComparator typeComparator = new StandardTypeComparator();
private TypeConverter typeConverter = new StandardTypeConverter(); private TypeConverter typeConverter = new StandardTypeConverter();
private TypeComparator typeComparator = new StandardTypeComparator();
private OperatorOverloader operatorOverloader = new StandardOperatorOverloader(); private OperatorOverloader operatorOverloader = new StandardOperatorOverloader();
private final Map<String, Object> variables = new HashMap<String, Object>();
public StandardEvaluationContext() { public StandardEvaluationContext() {
this.methodResolvers.add(new ReflectiveMethodResolver()); this.methodResolvers.add(new ReflectiveMethodResolver());
this.constructorResolvers.add(new ReflectiveConstructorResolver()); this.constructorResolvers.add(new ReflectiveConstructorResolver());
...@@ -74,34 +75,19 @@ public class StandardEvaluationContext implements EvaluationContext { ...@@ -74,34 +75,19 @@ public class StandardEvaluationContext implements EvaluationContext {
setRootObject(rootObject); setRootObject(rootObject);
} }
public void setRootObject(Object rootObject) { public void setRootObject(Object rootObject) {
this.rootObject = new TypedValue(rootObject,TypeDescriptor.forObject(rootObject)); this.rootObject = new TypedValue(rootObject, TypeDescriptor.forObject(rootObject));
} }
public void setRootObject(Object rootObject, TypeDescriptor typeDescriptor) { public void setRootObject(Object rootObject, TypeDescriptor typeDescriptor) {
this.rootObject = new TypedValue(rootObject,typeDescriptor); this.rootObject = new TypedValue(rootObject, typeDescriptor);
} }
public TypedValue getRootObject() { public TypedValue getRootObject() {
return this.rootObject; return this.rootObject;
} }
public void setVariable(String name, Object value) {
this.variables.put(name, value);
}
public void setVariables(Map<String,Object> variables) {
this.variables.putAll(variables);
}
public void registerFunction(String name, Method method) {
this.variables.put(name, method);
}
public Object lookupVariable(String name) {
return this.variables.get(name);
}
public void addConstructorResolver(ConstructorResolver resolver) { public void addConstructorResolver(ConstructorResolver resolver) {
this.constructorResolvers.add(this.constructorResolvers.size() - 1, resolver); this.constructorResolvers.add(this.constructorResolvers.size() - 1, resolver);
} }
...@@ -135,15 +121,6 @@ public class StandardEvaluationContext implements EvaluationContext { ...@@ -135,15 +121,6 @@ public class StandardEvaluationContext implements EvaluationContext {
return this.typeLocator; return this.typeLocator;
} }
public void setTypeComparator(TypeComparator typeComparator) {
Assert.notNull(typeComparator, "TypeComparator must not be null");
this.typeComparator = typeComparator;
}
public TypeComparator getTypeComparator() {
return this.typeComparator;
}
public void setTypeConverter(TypeConverter typeConverter) { public void setTypeConverter(TypeConverter typeConverter) {
Assert.notNull(typeConverter, "TypeConverter must not be null"); Assert.notNull(typeConverter, "TypeConverter must not be null");
this.typeConverter = typeConverter; this.typeConverter = typeConverter;
...@@ -153,6 +130,15 @@ public class StandardEvaluationContext implements EvaluationContext { ...@@ -153,6 +130,15 @@ public class StandardEvaluationContext implements EvaluationContext {
return this.typeConverter; return this.typeConverter;
} }
public void setTypeComparator(TypeComparator typeComparator) {
Assert.notNull(typeComparator, "TypeComparator must not be null");
this.typeComparator = typeComparator;
}
public TypeComparator getTypeComparator() {
return this.typeComparator;
}
public void setOperatorOverloader(OperatorOverloader operatorOverloader) { public void setOperatorOverloader(OperatorOverloader operatorOverloader) {
Assert.notNull(operatorOverloader, "OperatorOverloader must not be null"); Assert.notNull(operatorOverloader, "OperatorOverloader must not be null");
this.operatorOverloader = operatorOverloader; this.operatorOverloader = operatorOverloader;
...@@ -162,4 +148,20 @@ public class StandardEvaluationContext implements EvaluationContext { ...@@ -162,4 +148,20 @@ public class StandardEvaluationContext implements EvaluationContext {
return this.operatorOverloader; return this.operatorOverloader;
} }
public void setVariable(String name, Object value) {
this.variables.put(name, value);
}
public void setVariables(Map<String,Object> variables) {
this.variables.putAll(variables);
}
public void registerFunction(String name, Method method) {
this.variables.put(name, method);
}
public Object lookupVariable(String name) {
return this.variables.get(name);
}
} }
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.expression.spel; package org.springframework.expression.spel;
import java.util.HashMap; import java.util.HashMap;
...@@ -29,7 +30,6 @@ import org.springframework.expression.TypedValue; ...@@ -29,7 +30,6 @@ import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.testresources.Inventor; import org.springframework.expression.spel.testresources.Inventor;
/** /**
* Tests for the expression state object - some features are not yet exploited in the language (eg nested scopes) * Tests for the expression state object - some features are not yet exploited in the language (eg nested scopes)
* *
...@@ -47,7 +47,6 @@ public class ExpressionStateTests extends ExpressionTestCase { ...@@ -47,7 +47,6 @@ public class ExpressionStateTests extends ExpressionTestCase {
// Local variables are in variable scopes which come and go during evaluation. Normal variables are // Local variables are in variable scopes which come and go during evaluation. Normal variables are
// accessible through the evaluation context // accessible through the evaluation context
@Test @Test
public void testLocalVariables() { public void testLocalVariables() {
ExpressionState state = getState(); ExpressionState state = getState();
...@@ -62,7 +61,6 @@ public class ExpressionStateTests extends ExpressionTestCase { ...@@ -62,7 +61,6 @@ public class ExpressionStateTests extends ExpressionTestCase {
state.setLocalVariable("foo",null); state.setLocalVariable("foo",null);
value = state.lookupLocalVariable("foo"); value = state.lookupLocalVariable("foo");
Assert.assertEquals(null,value); Assert.assertEquals(null,value);
} }
@Test @Test
...@@ -119,8 +117,8 @@ public class ExpressionStateTests extends ExpressionTestCase { ...@@ -119,8 +117,8 @@ public class ExpressionStateTests extends ExpressionTestCase {
ExpressionState state = getState(); ExpressionState state = getState();
Assert.assertEquals(Inventor.class,state.getRootContextObject().getValue().getClass()); Assert.assertEquals(Inventor.class,state.getRootContextObject().getValue().getClass());
state.getEvaluationContext().setRootObject(null); ((StandardEvaluationContext) state.getEvaluationContext()).setRootObject(null);
Assert.assertEquals(null,state.getRootContextObject().getValue()); Assert.assertEquals(null, state.getRootContextObject().getValue());
state = new ExpressionState(new StandardEvaluationContext()); state = new ExpressionState(new StandardEvaluationContext());
Assert.assertEquals(TypedValue.NULL_TYPED_VALUE,state.getRootContextObject()); Assert.assertEquals(TypedValue.NULL_TYPED_VALUE,state.getRootContextObject());
...@@ -259,4 +257,5 @@ public class ExpressionStateTests extends ExpressionTestCase { ...@@ -259,4 +257,5 @@ public class ExpressionStateTests extends ExpressionTestCase {
ExpressionState state = new ExpressionState(context); ExpressionState state = new ExpressionState(context);
return state; return state;
} }
} }
...@@ -48,8 +48,6 @@ public class SpelDocumentationTests extends ExpressionTestCase { ...@@ -48,8 +48,6 @@ public class SpelDocumentationTests extends ExpressionTestCase {
static Inventor tesla ; static Inventor tesla ;
static Inventor pupin ; static Inventor pupin ;
static { static {
GregorianCalendar c = new GregorianCalendar(); GregorianCalendar c = new GregorianCalendar();
...@@ -115,7 +113,7 @@ public class SpelDocumentationTests extends ExpressionTestCase { ...@@ -115,7 +113,7 @@ public class SpelDocumentationTests extends ExpressionTestCase {
ExpressionParser parser = new SpelExpressionParser(); ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("name"); Expression exp = parser.parseExpression("name");
EvaluationContext context = new StandardEvaluationContext(); StandardEvaluationContext context = new StandardEvaluationContext();
context.setRootObject(tesla); context.setRootObject(tesla);
String name = (String) exp.getValue(context); String name = (String) exp.getValue(context);
...@@ -124,10 +122,9 @@ public class SpelDocumentationTests extends ExpressionTestCase { ...@@ -124,10 +122,9 @@ public class SpelDocumentationTests extends ExpressionTestCase {
@Test @Test
public void testEqualityCheck() throws Exception { public void testEqualityCheck() throws Exception {
ExpressionParser parser = new SpelExpressionParser(); ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext(); StandardEvaluationContext context = new StandardEvaluationContext();
context.setRootObject(tesla); context.setRootObject(tesla);
Expression exp = parser.parseExpression("name == 'Nikola Tesla'"); Expression exp = parser.parseExpression("name == 'Nikola Tesla'");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册