函数
您可以通过使用 #functionName(…)
语法在表达式中调用用户定义的函数来扩展 SpEL。函数可以通过 EvaluationContext
实现的 setVariable()
方法注册为变量。
|
由于函数与评估上下文中的 变量 共享一个公共命名空间,因此必须注意确保函数名称和变量名称不重叠。 |
以下示例展示了如何使用 java.lang.reflect.Method
注册一个用户定义的函数,以便通过反射调用它。
-
Java
-
Kotlin
Method method = ...;
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
context.setVariable("myFunction", method);
val method: Method = ...
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
context.setVariable("myFunction", method)
例如,考虑以下反转字符串的实用程序方法
-
Java
-
Kotlin
public abstract class StringUtils {
public static String reverseString(String input) {
return new StringBuilder(input).reverse().toString();
}
}
fun reverseString(input: String): String {
return StringBuilder(input).reverse().toString()
}
您可以注册并使用上述方法,如下面的示例所示
-
Java
-
Kotlin
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
context.setVariable("reverseString",
StringUtils.class.getMethod("reverseString", String.class));
// evaluates to "olleh"
String helloWorldReversed = parser.parseExpression(
"#reverseString('hello')").getValue(context, String.class);
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
context.setVariable("reverseString", ::reverseString.javaMethod)
// evaluates to "olleh"
val helloWorldReversed = parser.parseExpression(
"#reverseString('hello')").getValue(context, String::class.java)
函数也可以注册为 java.lang.invoke.MethodHandle
。如果 MethodHandle
目标和参数在注册之前已完全绑定,则这将使潜在的更有效的用例成为可能;但是,也支持部分绑定的句柄。
考虑 String#formatted(String, Object…)
实例方法,该方法根据模板和可变数量的参数生成消息。
您可以将 formatted
方法注册并用作 MethodHandle
,如下面的示例所示
-
Java
-
Kotlin
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
MethodHandle mh = MethodHandles.lookup().findVirtual(String.class, "formatted",
MethodType.methodType(String.class, Object[].class));
context.setVariable("message", mh);
// evaluates to "Simple message: <Hello World>"
String message = parser.parseExpression("#message('Simple message: <%s>', 'Hello World', 'ignored')")
.getValue(context, String.class);
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
val mh = MethodHandles.lookup().findVirtual(String::class.java, "formatted",
MethodType.methodType(String::class.java, Array<Any>::class.java))
context.setVariable("message", mh)
// evaluates to "Simple message: <Hello World>"
val message = parser.parseExpression("#message('Simple message: <%s>', 'Hello World', 'ignored')")
.getValue(context, String::class.java)
如上所述,绑定 MethodHandle
并注册绑定的 MethodHandle
也受支持。如果目标和所有参数都已绑定,这可能会提高性能。在这种情况下,SpEL 表达式中不需要任何参数,如下例所示
-
Java
-
Kotlin
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
String template = "This is a %s message with %s words: <%s>";
Object varargs = new Object[] { "prerecorded", 3, "Oh Hello World!", "ignored" };
MethodHandle mh = MethodHandles.lookup().findVirtual(String.class, "formatted",
MethodType.methodType(String.class, Object[].class))
.bindTo(template)
.bindTo(varargs); //here we have to provide arguments in a single array binding
context.setVariable("message", mh);
// evaluates to "This is a prerecorded message with 3 words: <Oh Hello World!>"
String message = parser.parseExpression("#message()")
.getValue(context, String.class);
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
val template = "This is a %s message with %s words: <%s>"
val varargs = arrayOf("prerecorded", 3, "Oh Hello World!", "ignored")
val mh = MethodHandles.lookup().findVirtual(String::class.java, "formatted",
MethodType.methodType(String::class.java, Array<Any>::class.java))
.bindTo(template)
.bindTo(varargs) //here we have to provide arguments in a single array binding
context.setVariable("message", mh)
// evaluates to "This is a prerecorded message with 3 words: <Oh Hello World!>"
val message = parser.parseExpression("#message()")
.getValue(context, String::class.java)