方法 (Methods)
你可以使用典型的 Java 编程语法来调用方法。你也可以直接在字面量(如字符串或数值)上调用方法。SpEL 也支持可变参数 (Varargs)。
以下示例演示了如何调用方法:
java
// 在字符串字面量上调用方法,评估结果为 "bc"
String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);
// 评估结果为 true(在社会对象上下文中调用 isMember 方法)
boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
societyContext, Boolean.class);kotlin
// 在字符串字面量上调用方法,评估结果为 "bc"
val bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String::class.java)
// 评估结果为 true(在社会对象上下文中调用 isMember 方法)
val isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
societyContext, Boolean::class.java)补充教学
1. 方法调用的作用域 (Scope)
在 SpEL 中,方法调用的行为取决于它作用的对象:
- 根对象方法:如果你直接在表达式中写
isMember(...),SpEL 会尝试在解析时指定的 根对象 (Root Object) 上寻找该方法。 - 字面量方法:如
'abc'.toUpperCase(),这是对标准 Java 类的实例方法调用。 - 静态方法:必须结合
T()运算符使用,例如T(java.lang.Math).abs(-10)。
2. 这里的 isMember 是哪里来的?
在官方文档的示例中,societyContext 指向了一个特定的对象(通常是 Society 类),而 isMember 是该类的一个公共方法。 在实际开发中,这常用于:
- Security 判定:调用权限检查服务的方法,如
hasRole('ADMIN')。 - 动态计算:调用工具类方法来格式化属性值。
3. 可变参数 (Varargs) 的便捷性
SpEL 完美支持 Java 的可变参数语法。如果一个方法定义为 void doSomething(String... args),你在 SpEL 中既可以传递数组,也可以直接平铺传入:doSomething('a', 'b', 'c')。SpEL 会自动帮你打包成数组。
4. 方法解析器 (MethodResolver)
背后的原理是:SpEL 使用一组 MethodResolver 来查找匹配的方法。
- 反射机制:默认情况下通过反射查找公共方法。
- 性能考量:频繁的方法调用可能产生反射开销。如果性能是瓶颈,可以考虑开启 SpEL 编译模式,它会试图将频繁调用的方法生成为直接调用的字节码。
5. 方法调用 vs 属性访问
SpEL 会智能处理两者的区别。如果你写 user.name,SpEL 会先尝试查找 getName() 方法;如果你写 user.getName(),效果是一样的,但显式调用方法可以传递参数,而属性访问则不行。