Skip to content

方法 (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(),效果是一样的,但显式调用方法可以传递参数,而属性访问则不行。

Based on Spring Framework.