此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Data Commons 3.3.4! |
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Data Commons 3.3.4! |
值表达式是 Spring 表达式语言 (SpEL) 和属性占位符解析的组合。
它们将强大的编程表达式计算与采用属性占位符解析来从配置属性等获取值的简单性相结合。Environment
表达式应由可信输入(如注释值)定义,而不是根据用户输入确定。
以下代码演示如何在注释上下文中使用表达式。
@Document("orders-#{tenantService.getOrderCollection()}-${tenant-config.suffix}")
class Order {
// …
}
值表达式可以从唯一的 SPEL 表达式、属性占位符或混合各种表达式(包括文字)的复合表达式中定义。
#{tenantService.getOrderCollection()} (1)
#{(1+1) + '-hello-world'} (2)
${tenant-config.suffix} (3)
orders-${tenant-config.suffix} (4)
#{tenantService.getOrderCollection()}-${tenant-config.suffix} (5)
1 | 使用单个 SpEL 表达式的值表达式。 |
2 | 使用静态 SpEL 表达式的 Value Expression 计算结果为 。2-hello-world |
3 | 使用单个 Property Placeholder 的值表达式。 |
4 | 由 Literal 和 Property Placeholder 组成的复合表达式 。orders- ${tenant-config.suffix} |
5 | 使用 SpEL、属性占位符和文字的复合表达式。 |
使用值表达式为您的代码带来了很大的灵活性。 这样做需要对每个使用情况的表达式进行评估,因此,值表达式评估会影响性能配置文件。 |
1 | 使用单个 SpEL 表达式的值表达式。 |
2 | 使用静态 SpEL 表达式的 Value Expression 计算结果为 。2-hello-world |
3 | 使用单个 Property Placeholder 的值表达式。 |
4 | 由 Literal 和 Property Placeholder 组成的复合表达式 。orders- ${tenant-config.suffix} |
5 | 使用 SpEL、属性占位符和文字的复合表达式。 |
使用值表达式为您的代码带来了很大的灵活性。 这样做需要对每个使用情况的表达式进行评估,因此,值表达式评估会影响性能配置文件。 |
解析和评估
值表达式由 API 解析。
的实例是线程安全的,可以缓存以供以后使用,以避免重复解析。ValueExpressionParser
ValueExpression
以下示例显示了 Value Expression API 的用法:
-
Java
-
Kotlin
ValueParserConfiguration configuration = SpelExpressionParser::new;
ValueEvaluationContext context = ValueEvaluationContext.of(environment, evaluationContext);
ValueExpressionParser parser = ValueExpressionParser.create(configuration);
ValueExpression expression = parser.parse("Hello, World");
Object result = expression.evaluate(context);
val configuration = ValueParserConfiguration { SpelExpressionParser() }
val context = ValueEvaluationContext.of(environment, evaluationContext)
val parser = ValueExpressionParser.create(configuration)
val expression: ValueExpression = parser.parse("Hello, World")
val result: Any = expression.evaluate(context)
SPEL 表达式
SPEL 表达式遵循 Template 样式,其中表达式应包含在格式中。
表达式使用 提供的 进行计算。
上下文本身很强大,允许进行广泛的操作、访问静态类型和上下文扩展。#{…}
EvaluationContext
EvaluationContextProvider
StandardEvaluationContext
确保仅分析和评估来自可信来源(如注释)的表达式。 接受用户提供的表达式可以创建一个入口路径来利用应用程序上下文和您的系统,从而导致潜在的安全漏洞。 |
扩展 Evaluation 上下文
EvaluationContextProvider
及其响应式变体提供对 . 及其 reactive 变体是默认实现,用于从 application context(特别是 .ReactiveEvaluationContextProvider
EvaluationContext
ExtensionAwareEvaluationContextProvider
ReactiveExtensionAwareEvaluationContextProvider
ListableBeanFactory
扩展实施 or 以提供对 hydrate 的扩展支持 。
它们是根对象、属性和函数(顶级方法)。EvaluationContextExtension
ReactiveEvaluationContextExtension
EvaluationContext
以下示例显示了一个上下文扩展,该扩展提供根对象、属性、函数和别名函数。
EvaluationContextExtension
-
Java
-
Kotlin
@Component
public class MyExtension implements EvaluationContextExtension {
@Override
public String getExtensionId() {
return "my-extension";
}
@Override
public Object getRootObject() {
return new CustomExtensionRootObject();
}
@Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<>();
properties.put("key", "Hello");
return properties;
}
@Override
public Map<String, Function> getFunctions() {
Map<String, Function> functions = new HashMap<>();
try {
functions.put("aliasedMethod", new Function(getClass().getMethod("extensionMethod")));
return functions;
} catch (Exception o_O) {
throw new RuntimeException(o_O);
}
}
public static String extensionMethod() {
return "Hello World";
}
public static int add(int i1, int i2) {
return i1 + i2;
}
}
public class CustomExtensionRootObject {
public boolean rootObjectInstanceMethod() {
return true;
}
}
@Component
class MyExtension : EvaluationContextExtension {
override fun getExtensionId(): String {
return "my-extension"
}
override fun getRootObject(): Any? {
return CustomExtensionRootObject()
}
override fun getProperties(): Map<String, Any> {
val properties: MutableMap<String, Any> = HashMap()
properties["key"] = "Hello"
return properties
}
override fun getFunctions(): Map<String, Function> {
val functions: MutableMap<String, Function> = HashMap()
try {
functions["aliasedMethod"] = Function(javaClass.getMethod("extensionMethod"))
return functions
} catch (o_O: Exception) {
throw RuntimeException(o_O)
}
}
companion object {
fun extensionMethod(): String {
return "Hello World"
}
fun add(i1: Int, i2: Int): Int {
return i1 + i2
}
}
}
class CustomExtensionRootObject {
fun rootObjectInstanceMethod(): Boolean {
return true
}
}
注册上面显示的扩展后,您可以使用其导出的方法、属性和根对象来评估 SPEL 表达式:
#{add(1, 2)} (1)
#{extensionMethod()} (2)
#{aliasedMethod()} (3)
#{key} (4)
#{rootObjectInstanceMethod()} (5)
1 | 调用由 resulting in 声明的方法,因为该方法会添加两个数值参数并返回 sum。add MyExtension 3 |
2 | 调用由结果声明的方法。extensionMethod MyExtension Hello World |
3 | 调用方法 .
该方法作为函数公开,并重定向到通过生成 .aliasedMethod extensionMethod MyExtension Hello World |
4 | 评估生成 的属性。key Hello |
5 | 在 root object instance 上调用该方法 。rootObjectInstanceMethod CustomExtensionRootObject |
您可以在 SecurityEvaluationContextExtension
中找到真实的上下文扩展。
确保仅分析和评估来自可信来源(如注释)的表达式。 接受用户提供的表达式可以创建一个入口路径来利用应用程序上下文和您的系统,从而导致潜在的安全漏洞。 |
1 | 调用由 resulting in 声明的方法,因为该方法会添加两个数值参数并返回 sum。add MyExtension 3 |
2 | 调用由结果声明的方法。extensionMethod MyExtension Hello World |
3 | 调用方法 .
该方法作为函数公开,并重定向到通过生成 .aliasedMethod extensionMethod MyExtension Hello World |
4 | 评估生成 的属性。key Hello |
5 | 在 root object instance 上调用该方法 。rootObjectInstanceMethod CustomExtensionRootObject |
属性占位符
表单后面的属性占位符是指通常由 a 到 提供的属性。
属性对于根据系统属性、应用程序配置文件、环境配置或 secret 管理系统提供的属性源进行解析非常有用。
您可以在 Spring Framework 的 @Value
用法文档中找到有关属性占位符的更多详细信息。${…}
PropertySource
Environment