parent
58011f71e9
commit
cb8c6e3251
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2018 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.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.expression.spel.support;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.expression.BeanResolver;
|
||||||
|
import org.springframework.expression.ConstructorResolver;
|
||||||
|
import org.springframework.expression.EvaluationContext;
|
||||||
|
import org.springframework.expression.MethodResolver;
|
||||||
|
import org.springframework.expression.OperatorOverloader;
|
||||||
|
import org.springframework.expression.PropertyAccessor;
|
||||||
|
import org.springframework.expression.TypeComparator;
|
||||||
|
import org.springframework.expression.TypeConverter;
|
||||||
|
import org.springframework.expression.TypeLocator;
|
||||||
|
import org.springframework.expression.TypedValue;
|
||||||
|
import org.springframework.expression.spel.SpelEvaluationException;
|
||||||
|
import org.springframework.expression.spel.SpelMessage;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A basic implementation of {@link EvaluationContext} that focuses on a subset
|
||||||
|
* of essential SpEL features and configuration options, and relies on default
|
||||||
|
* strategies otherwise.
|
||||||
|
*
|
||||||
|
* <p>In many cases, the full extent of the SpEL is not
|
||||||
|
* required and should be meaningfully restricted. Examples include but are not
|
||||||
|
* limited to data binding expressions, property-based filters, and others. To
|
||||||
|
* that effect, {@code SimpleEvaluationContext} supports only a subset of the
|
||||||
|
* SpEL language syntax that excludes references to Java types, constructors,
|
||||||
|
* and bean references.
|
||||||
|
*
|
||||||
|
* <p>Note that {@code SimpleEvaluationContext} cannot be configured with a
|
||||||
|
* default root object. Instead it is meant to be created once and used
|
||||||
|
* repeatedly through method variants on
|
||||||
|
* {@link org.springframework.expression.Expression Expression} that accept
|
||||||
|
* both an {@code EvaluationContext} and a root object.
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 4.3.15
|
||||||
|
*/
|
||||||
|
public class SimpleEvaluationContext implements EvaluationContext {
|
||||||
|
|
||||||
|
private static final TypeLocator typeNotFoundTypeLocator = typeName -> {
|
||||||
|
throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private final List<PropertyAccessor> propertyAccessors;
|
||||||
|
|
||||||
|
private final List<ConstructorResolver> constructorResolvers =
|
||||||
|
Collections.singletonList(new ReflectiveConstructorResolver());
|
||||||
|
|
||||||
|
private final List<MethodResolver> methodResolvers =
|
||||||
|
Collections.singletonList(new ReflectiveMethodResolver());
|
||||||
|
|
||||||
|
private final TypeConverter typeConverter;
|
||||||
|
|
||||||
|
private final TypeComparator typeComparator = new StandardTypeComparator();
|
||||||
|
|
||||||
|
private final OperatorOverloader operatorOverloader = new StandardOperatorOverloader();
|
||||||
|
|
||||||
|
private final Map<String, Object> variables = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
public SimpleEvaluationContext() {
|
||||||
|
this(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleEvaluationContext(@Nullable List<PropertyAccessor> accessors, @Nullable TypeConverter converter) {
|
||||||
|
this.propertyAccessors = initPropertyAccessors(accessors);
|
||||||
|
this.typeConverter = converter != null ? converter : new StandardTypeConverter();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static List<PropertyAccessor> initPropertyAccessors(@Nullable List<PropertyAccessor> accessors) {
|
||||||
|
if (accessors == null) {
|
||||||
|
accessors = new ArrayList<>(5);
|
||||||
|
accessors.add(new ReflectivePropertyAccessor());
|
||||||
|
}
|
||||||
|
return accessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code SimpleEvaluationContext} cannot be configured with a root object.
|
||||||
|
* It is meant for repeated use with
|
||||||
|
* {@link org.springframework.expression.Expression Expression} method
|
||||||
|
* variants that accept both an {@code EvaluationContext} and a root object.
|
||||||
|
* @return Always returns {@link TypedValue#NULL}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TypedValue getRootObject() {
|
||||||
|
return TypedValue.NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PropertyAccessor> getPropertyAccessors() {
|
||||||
|
return this.propertyAccessors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a single {@link ReflectiveConstructorResolver}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<ConstructorResolver> getConstructorResolvers() {
|
||||||
|
return this.constructorResolvers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a single {@link ReflectiveMethodResolver}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<MethodResolver> getMethodResolvers() {
|
||||||
|
return this.methodResolvers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code SimpleEvaluationContext} does not support use of bean references.
|
||||||
|
* @return Always returns {@code null}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public BeanResolver getBeanResolver() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code SimpleEvaluationContext} does not support use of type references.
|
||||||
|
* @return {@code TypeLocator} implementation that raises a
|
||||||
|
* {@link SpelEvaluationException} with {@link SpelMessage#TYPE_NOT_FOUND}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TypeLocator getTypeLocator() {
|
||||||
|
return typeNotFoundTypeLocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configured {@link TypeConverter}.
|
||||||
|
* <p>By default this is {@link StandardTypeConverter}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TypeConverter getTypeConverter() {
|
||||||
|
return this.typeConverter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an instance of {@link StandardTypeComparator}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TypeComparator getTypeComparator() {
|
||||||
|
return this.typeComparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an instance of {@link StandardOperatorOverloader}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public OperatorOverloader getOperatorOverloader() {
|
||||||
|
return this.operatorOverloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVariable(String name, @Nullable Object value) {
|
||||||
|
this.variables.put(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Object lookupVariable(String name) {
|
||||||
|
return this.variables.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -36,13 +36,7 @@ syntax. In several places an Inventor and Inventor's Society class are used as t
|
||||||
target objects for expression evaluation. These class declarations and the data used to
|
target objects for expression evaluation. These class declarations and the data used to
|
||||||
populate them are listed at the end of the chapter.
|
populate them are listed at the end of the chapter.
|
||||||
|
|
||||||
|
The expression language supports the following functionality:
|
||||||
|
|
||||||
|
|
||||||
[[expressions-features]]
|
|
||||||
== Feature overview
|
|
||||||
|
|
||||||
The expression language supports the following functionality
|
|
||||||
|
|
||||||
* Literal expressions
|
* Literal expressions
|
||||||
* Boolean and relational operators
|
* Boolean and relational operators
|
||||||
|
@ -68,7 +62,7 @@ The expression language supports the following functionality
|
||||||
|
|
||||||
|
|
||||||
[[expressions-evaluation]]
|
[[expressions-evaluation]]
|
||||||
== Expression evaluation using Spring's Expression interface
|
== Evaluation
|
||||||
|
|
||||||
This section introduces the simple use of SpEL interfaces and its expression language.
|
This section introduces the simple use of SpEL interfaces and its expression language.
|
||||||
The complete language reference can be found in the section
|
The complete language reference can be found in the section
|
||||||
|
@ -156,10 +150,9 @@ result type. An `EvaluationException` will be thrown if the value cannot be cast
|
||||||
type `T` or converted using the registered type converter.
|
type `T` or converted using the registered type converter.
|
||||||
|
|
||||||
The more common usage of SpEL is to provide an expression string that is evaluated
|
The more common usage of SpEL is to provide an expression string that is evaluated
|
||||||
against a specific object instance (called the root object). There are two options here
|
against a specific object instance (called the root object). The example shows
|
||||||
and which to choose depends on whether the object against which the expression is being
|
how to retrieve the `name` property from an instance of the `Inventor` class or
|
||||||
evaluated will be changing with each call to evaluate the expression. In the following
|
create a boolean condition:
|
||||||
example we retrieve the `name` property from an instance of the Inventor class.
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
@ -172,88 +165,38 @@ example we retrieve the `name` property from an instance of the Inventor class.
|
||||||
Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
|
Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
|
||||||
|
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
Expression exp = parser.parseExpression("**name**");
|
|
||||||
|
|
||||||
EvaluationContext context = new StandardEvaluationContext(tesla);
|
|
||||||
String name = (String) exp.getValue(context);
|
|
||||||
----
|
|
||||||
|
|
||||||
In the last line, the value of the string variable `name` will be set to "Nikola Tesla".
|
|
||||||
The class StandardEvaluationContext is where you can specify which object the "name"
|
|
||||||
property will be evaluated against. This is the mechanism to use if the root object is
|
|
||||||
unlikely to change, it can simply be set once in the evaluation context. If the root
|
|
||||||
object is likely to change repeatedly, it can be supplied on each call to `getValue`, as
|
|
||||||
this next example shows:
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
|
||||||
[subs="verbatim,quotes"]
|
|
||||||
----
|
|
||||||
/ Create and set a calendar
|
|
||||||
GregorianCalendar c = new GregorianCalendar();
|
|
||||||
c.set(1856, 7, 9);
|
|
||||||
|
|
||||||
// The constructor arguments are name, birthday, and nationality.
|
|
||||||
Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
|
|
||||||
|
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
|
||||||
Expression exp = parser.parseExpression("**name**");
|
Expression exp = parser.parseExpression("**name**");
|
||||||
String name = (String) exp.getValue(tesla);
|
String name = (String) exp.getValue(tesla);
|
||||||
----
|
// name == "Nikola Tesla"
|
||||||
|
|
||||||
In this case the inventor `tesla` has been supplied directly to `getValue` and the
|
exp = parser.parseExpression("name == 'Nikola Tesla'");
|
||||||
expression evaluation infrastructure creates and manages a default evaluation context
|
boolean result = exp.getValue(tesla, Boolean.class);
|
||||||
internally - it did not require one to be supplied.
|
// result == true
|
||||||
|
|
||||||
The StandardEvaluationContext is relatively expensive to construct and during repeated
|
|
||||||
usage it builds up cached state that enables subsequent expression evaluations to be
|
|
||||||
performed more quickly. For this reason it is better to cache and reuse them where
|
|
||||||
possible, rather than construct a new one for each expression evaluation.
|
|
||||||
|
|
||||||
In some cases it can be desirable to use a configured evaluation context and yet still
|
|
||||||
supply a different root object on each call to `getValue`. `getValue` allows both to be
|
|
||||||
specified on the same call. In these situations the root object passed on the call is
|
|
||||||
considered to override any (which maybe null) specified on the evaluation context.
|
|
||||||
|
|
||||||
[NOTE]
|
|
||||||
====
|
|
||||||
In standalone usage of SpEL there is a need to create the parser, parse expressions and
|
|
||||||
perhaps provide evaluation contexts and a root context object. However, more common
|
|
||||||
usage is to provide only the SpEL expression string as part of a configuration file, for
|
|
||||||
example for Spring bean or Spring Web Flow definitions. In this case, the parser,
|
|
||||||
evaluation context, root object and any predefined variables are all set up implicitly,
|
|
||||||
requiring the user to specify nothing other than the expressions.
|
|
||||||
====
|
|
||||||
|
|
||||||
As a final introductory example, the use of a boolean operator is shown using the
|
|
||||||
Inventor object in the previous example.
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
|
||||||
[subs="verbatim,quotes"]
|
|
||||||
----
|
|
||||||
Expression exp = parser.parseExpression("name == 'Nikola Tesla'");
|
|
||||||
boolean result = exp.getValue(context, Boolean.class); // evaluates to true
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[expressions-evaluation-context]]
|
[[expressions-evaluation-context]]
|
||||||
=== The EvaluationContext interface
|
=== `EvaluationContext`
|
||||||
|
|
||||||
The interface `EvaluationContext` is used when evaluating an expression to resolve
|
The interface `EvaluationContext` is used when evaluating an expression to resolve
|
||||||
properties, methods, fields, and to help perform type conversion. The out-of-the-box
|
properties, methods, fields, and to help perform type conversion. The out-of-the-box
|
||||||
implementation, `StandardEvaluationContext`, uses reflection to manipulate the object,
|
implementations, `SimpleEvalutationContext` and `StandardEvaluationContext`, use
|
||||||
caching `java.lang.reflect.Method`, `java.lang.reflect.Field`, and
|
reflection to manipulate the object, caching `java.lang.reflect.Method`,
|
||||||
`java.lang.reflect.Constructor` instances for increased performance.
|
`java.lang.reflect.Field`, and `java.lang.reflect.Constructor` instances for increased
|
||||||
|
performance.
|
||||||
|
|
||||||
The `StandardEvaluationContext` is where you may specify the root object to evaluate
|
`SimpleEvaluationContext` exposes a subset of essential SpEL language features and
|
||||||
against via the method `setRootObject()` or passing the root object into the
|
configuration options. Certain categories of expressions, do not require the full extent
|
||||||
constructor. You can also specify variables and functions that will be used in the
|
of the SpEL language syntax and arguably should be meaningfully restricted. Examples
|
||||||
expression using the methods `setVariable()` and `registerFunction()`. The use of
|
include but are not limited to data binding expressions, property-based filters, and
|
||||||
variables and functions are described in the language reference sections
|
others. To effect, `SimpleEvaluationContext` supports a subset of the SpEL language syntax
|
||||||
<<expressions-ref-variables,Variables>> and <<expressions-ref-functions,Functions>>. The
|
that excludes references to Java types, constructors, and bean references.
|
||||||
`StandardEvaluationContext` is also where you can register custom
|
|
||||||
``ConstructorResolver``s, ``MethodResolver``s, and ``PropertyAccessor``s to extend how SpEL
|
`StandardEvaluationContext` exposes the full set of SpEL language features and
|
||||||
evaluates expressions. Please refer to the javadoc of these classes for more details.
|
configuration options. You may use it to specify a default root object, and to configure
|
||||||
|
every available evaluation-related strategy.
|
||||||
|
|
||||||
|
|
||||||
[[expressions-type-conversion]]
|
[[expressions-type-conversion]]
|
||||||
|
@ -280,14 +223,14 @@ being placed in it. A simple example:
|
||||||
}
|
}
|
||||||
|
|
||||||
Simple simple = new Simple();
|
Simple simple = new Simple();
|
||||||
|
|
||||||
simple.booleanList.add(true);
|
simple.booleanList.add(true);
|
||||||
|
|
||||||
StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple);
|
SimpleEvaluationContext context = new SimpleEvaluationContext();
|
||||||
|
|
||||||
// false is passed in here as a string. SpEL and the conversion service will
|
// false is passed in here as a string. SpEL and the conversion service will
|
||||||
// correctly recognize that it needs to be a Boolean and convert it
|
// correctly recognize that it needs to be a Boolean and convert it
|
||||||
parser.parseExpression("booleanList[0]").setValue(simpleContext, "false");
|
|
||||||
|
parser.parseExpression("booleanList[0]").setValue(context, simple, "false");
|
||||||
|
|
||||||
// b will be false
|
// b will be false
|
||||||
Boolean b = simple.booleanList.get(0);
|
Boolean b = simple.booleanList.get(0);
|
||||||
|
@ -446,7 +389,7 @@ More and more types of expression will be compilable in the future.
|
||||||
|
|
||||||
|
|
||||||
[[expressions-beandef]]
|
[[expressions-beandef]]
|
||||||
== Expression support for defining bean definitions
|
== Expressions in bean definitions
|
||||||
|
|
||||||
SpEL expressions can be used with XML or annotation-based configuration metadata for
|
SpEL expressions can be used with XML or annotation-based configuration metadata for
|
||||||
defining ``BeanDefinition``s. In both cases the syntax to define the expression is of the
|
defining ``BeanDefinition``s. In both cases the syntax to define the expression is of the
|
||||||
|
@ -455,7 +398,7 @@ form `#{ <expression string> }`.
|
||||||
|
|
||||||
|
|
||||||
[[expressions-beandef-xml-based]]
|
[[expressions-beandef-xml-based]]
|
||||||
=== XML based configuration
|
=== XML configuration
|
||||||
|
|
||||||
A property or constructor-arg value can be set using expressions as shown below.
|
A property or constructor-arg value can be set using expressions as shown below.
|
||||||
|
|
||||||
|
@ -504,7 +447,7 @@ You can also refer to other bean properties by name, for example.
|
||||||
|
|
||||||
|
|
||||||
[[expressions-beandef-annotation-based]]
|
[[expressions-beandef-annotation-based]]
|
||||||
=== Annotation-based configuration
|
=== Annotation config
|
||||||
|
|
||||||
The `@Value` annotation can be placed on fields, methods and method/constructor
|
The `@Value` annotation can be placed on fields, methods and method/constructor
|
||||||
parameters to specify a default value.
|
parameters to specify a default value.
|
||||||
|
@ -659,25 +602,24 @@ arrays and lists are obtained using square bracket notation.
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
SimpleEvaluationContext context = new SimpleEvaluationContext();
|
||||||
|
|
||||||
// Inventions Array
|
// Inventions Array
|
||||||
StandardEvaluationContext teslaContext = new StandardEvaluationContext(tesla);
|
|
||||||
|
|
||||||
// evaluates to "Induction motor"
|
// evaluates to "Induction motor"
|
||||||
String invention = parser.parseExpression("inventions[3]").getValue(
|
String invention = parser.parseExpression("inventions[3]").getValue(
|
||||||
teslaContext, String.class);
|
context, tesla, String.class);
|
||||||
|
|
||||||
// Members List
|
// Members List
|
||||||
StandardEvaluationContext societyContext = new StandardEvaluationContext(ieee);
|
|
||||||
|
|
||||||
// evaluates to "Nikola Tesla"
|
// evaluates to "Nikola Tesla"
|
||||||
String name = parser.parseExpression("Members[0].Name").getValue(
|
String name = parser.parseExpression("Members[0].Name").getValue(
|
||||||
societyContext, String.class);
|
context, ieee, String.class);
|
||||||
|
|
||||||
// List and Array navigation
|
// List and Array navigation
|
||||||
// evaluates to "Wireless communication"
|
// evaluates to "Wireless communication"
|
||||||
String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(
|
String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(
|
||||||
societyContext, String.class);
|
context, ieee, String.class);
|
||||||
----
|
----
|
||||||
|
|
||||||
The contents of maps are obtained by specifying the literal key value within the
|
The contents of maps are obtained by specifying the literal key value within the
|
||||||
|
@ -943,14 +885,14 @@ done within a call to `setValue` but can also be done inside a call to `getValue
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
Inventor inventor = new Inventor();
|
Inventor inventor = new Inventor();
|
||||||
StandardEvaluationContext inventorContext = new StandardEvaluationContext(inventor);
|
SimpleEvaluationContext context = new SimpleEvaluationContext();
|
||||||
|
|
||||||
parser.parseExpression("Name").setValue(inventorContext, "Alexander Seovic2");
|
parser.parseExpression("Name").setValue(context, inventor, "Alexander Seovic2");
|
||||||
|
|
||||||
// alternatively
|
// alternatively
|
||||||
|
|
||||||
String aleks = parser.parseExpression(
|
String aleks = parser.parseExpression(
|
||||||
"Name = 'Alexandar Seovic'").getValue(inventorContext, String.class);
|
"Name = 'Alexandar Seovic'").getValue(context, inventor, String.class);
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
||||||
|
@ -1005,16 +947,16 @@ used).
|
||||||
=== Variables
|
=== Variables
|
||||||
|
|
||||||
Variables can be referenced in the expression using the syntax `#variableName`. Variables
|
Variables can be referenced in the expression using the syntax `#variableName`. Variables
|
||||||
are set using the method setVariable on the `StandardEvaluationContext`.
|
are set using the method setVariable on `EvaluationContext` implementations.
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext(tesla);
|
SimpleEvaluationContext context = new SimpleEvaluationContext();
|
||||||
context.setVariable("newName", "Mike Tesla");
|
context.setVariable("newName", "Mike Tesla");
|
||||||
|
|
||||||
parser.parseExpression("Name = #newName").getValue(context);
|
parser.parseExpression("Name = #newName").getValue(context, tesla);
|
||||||
|
|
||||||
System.out.println(tesla.getName()) // "Mike Tesla"
|
System.out.println(tesla.getName()) // "Mike Tesla"
|
||||||
----
|
----
|
||||||
|
@ -1037,7 +979,7 @@ an expression are evaluated, #root always refers to the root.
|
||||||
|
|
||||||
// create parser and set variable 'primes' as the array of integers
|
// create parser and set variable 'primes' as the array of integers
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
SimpleEvaluationContext context = new SimpleEvaluationContext();
|
||||||
context.setVariable("primes",primes);
|
context.setVariable("primes",primes);
|
||||||
|
|
||||||
// all prime numbers > 10 from the list (using selection ?{...})
|
// all prime numbers > 10 from the list (using selection ?{...})
|
||||||
|
@ -1052,17 +994,18 @@ an expression are evaluated, #root always refers to the root.
|
||||||
=== Functions
|
=== Functions
|
||||||
|
|
||||||
You can extend SpEL by registering user defined functions that can be called within the
|
You can extend SpEL by registering user defined functions that can be called within the
|
||||||
expression string. The function is registered with the `StandardEvaluationContext` using
|
expression string. The function is registered through the `EvaluationContext`.
|
||||||
the method.
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
public void registerFunction(String name, Method m)
|
Method method = ...;
|
||||||
|
|
||||||
|
SimpleEvaluationContext context = new SimpleEvaluationContext();
|
||||||
|
context.setVariable("myFunction", method);
|
||||||
----
|
----
|
||||||
|
|
||||||
A reference to a Java Method provides the implementation of the function. For example, a
|
For example, given a utility method to reverse a string is shown below:
|
||||||
utility method to reverse a string is shown below.
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
@ -1079,16 +1022,15 @@ utility method to reverse a string is shown below.
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
This method is then registered with the evaluation context and can be used within an
|
The above method can then be registered and used as follows:
|
||||||
expression string.
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
SimpleEvaluationContext context = new SimpleEvaluationContext();
|
||||||
|
|
||||||
context.registerFunction("reverseString",
|
context.setVariable("reverseString",
|
||||||
StringUtils.class.getDeclaredMethod("reverseString", String.class));
|
StringUtils.class.getDeclaredMethod("reverseString", String.class));
|
||||||
|
|
||||||
String helloWorldReversed = parser.parseExpression(
|
String helloWorldReversed = parser.parseExpression(
|
||||||
|
@ -1198,15 +1140,15 @@ Here is a more complex example.
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
|
||||||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext(tesla);
|
SimpleEvaluationContext context = new SimpleEvaluationContext();
|
||||||
|
|
||||||
String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, String.class);
|
String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class);
|
||||||
|
|
||||||
System.out.println(name); // Nikola Tesla
|
System.out.println(name); // Nikola Tesla
|
||||||
|
|
||||||
tesla.setName(null);
|
tesla.setName(null);
|
||||||
|
|
||||||
name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, String.class);
|
name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class);
|
||||||
|
|
||||||
System.out.println(name); // Elvis Presley
|
System.out.println(name); // Elvis Presley
|
||||||
----
|
----
|
||||||
|
@ -1230,14 +1172,14 @@ safe navigation operator will simply return null instead of throwing an exceptio
|
||||||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||||
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
|
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
|
||||||
|
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext(tesla);
|
SimpleEvaluationContext context = new SimpleEvaluationContext();
|
||||||
|
|
||||||
String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class);
|
String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
|
||||||
System.out.println(city); // Smiljan
|
System.out.println(city); // Smiljan
|
||||||
|
|
||||||
tesla.setPlaceOfBirth(null);
|
tesla.setPlaceOfBirth(null);
|
||||||
|
|
||||||
city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, String.class);
|
city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
|
||||||
|
|
||||||
System.out.println(city); // null - does not throw NullPointerException!!!
|
System.out.println(city); // null - does not throw NullPointerException!!!
|
||||||
----
|
----
|
||||||
|
|
Loading…
Reference in New Issue