- [Spel](#spel) - [Spel表达式计算](#spel表达式计算) - [示例](#示例) - [Concept](#concept) - [调用方法](#调用方法) - [调用属性](#调用属性) - [调用构造器](#调用构造器) - [在特定对象上计算表达式](#在特定对象上计算表达式) - [EvaluationContext](#evaluationcontext) - [EvaluationContext实现类](#evaluationcontext实现类) - [TypeConversion](#typeconversion) - [在定义Bean对象时使用Spel表达式](#在定义bean对象时使用spel表达式) - [为field指定默认值](#为field指定默认值) - [通过setter为field指定默认值](#通过setter为field指定默认值) - [@Autowired方法和构造器](#autowired方法和构造器) # Spel ## Spel表达式计算 ### 示例 如下是一个Spel表达式计算示例: ```java ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression("'Hello World'"); String message = (String) exp.getValue(); // 最终message计算的值是'Hello World' ``` ### Concept `ExpressionParser`接口用于对表达式字符串进行解析,在上述示例中,表达式字符串是一个由单引号包围起来的字符串字面量。 `Expression`接口则是负责对表达式字符串进行计算。 在调用`parser.parseExpression`和`exp.getValue`,分别会抛出`ParseException`和`EvaluationException`异常。 Spel支持许多特性,例如调用方法,访问属性,调用构造方法等,示例如下: #### 调用方法 ```java ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression("'Hello World'.concat('!')"); String message = (String) exp.getValue(); // message值为Hello World! ``` #### 调用属性 ```java ExpressionParser parser = new SpelExpressionParser(); // invokes 'getBytes().length' Expression exp = parser.parseExpression("'Hello World'.bytes.length"); int length = (Integer) exp.getValue(); ``` #### 调用构造器 ```java ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression("new String('hello world').toUpperCase()"); String message = exp.getValue(String.class); ``` 通过`public T getValue(Class desiredResultType)`方法,向getValue方法传递一个Class对象,可以避免在调用getValue方法调用之后需要将返回值手动转化为特定类型。如果类型转化失败,会抛出一个EvaluationException异常。 #### 在特定对象上计算表达式 Spel支持在一个特定的对象上(该对象通常被称作root object)进行计算,例如如下示例: ```java // 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"); // Parse name as an expression String name = (String) exp.getValue(tesla); // name == "Nikola Tesla" exp = parser.parseExpression("name == 'Nikola Tesla'"); boolean result = exp.getValue(tesla, Boolean.class); // result == true ``` ### EvaluationContext EvalutaionContext用于给表达式提供一个执行的上下文环境,通过EvalutaionContext,可以向context中放置一个变量,并且在后续中使用该变量: ```java // 向context中放入一个list变量 ctx.setVariable("list",list) // 在后续表达式中即可使用放入的list变量 // 获取放入context中的list变量的值 parser.parseExpression("#list[0]").getValue(ctx); // 设置context中list变量的值 parser.parseExpression("#list[0]").setValue(ctx , "false"); ``` #### EvaluationContext实现类 - SimpleEvaluationContext:实现了Spel语言的部分特性 - StandardEvaluationContext:实现了Spel语言的全部特性 ### TypeConversion 默认情况下,spel会使用`org.springframework.core.convert.ConversionService`中的Conversion Service。该conversion service包含内置的类型转换,并且可以为类型之间指定自定义的类型转换。该转换是支持泛型的。 如下为支持泛型的示例: ```java class Simple { public List booleanList = new ArrayList<>(); } Simple simple = new Simple(); simple.booleanList.add(true); EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build(); // "false" is passed in here as a String. SpEL and the conversion service // will recognize that it needs to be a Boolean and convert it accordingly. parser.parseExpression("booleanList[0]").setValue(context, simple, "false"); // b is false Boolean b = simple.booleanList.get(0); ``` ### 在定义Bean对象时使用Spel表达式 可以通过@Value注解来为bean对象的域、方法参数、构造器参数指定默认值。通过如下方式来指定表达式: - `#{ }.` #### 为field指定默认值 ```java public class FieldValueTestBean { @Value("#{ systemProperties['user.region'] }") private String defaultLocale; public void setDefaultLocale(String defaultLocale) { this.defaultLocale = defaultLocale; } public String getDefaultLocale() { return this.defaultLocale; } } ``` #### 通过setter为field指定默认值 ```java public class PropertyValueTestBean { private String defaultLocale; @Value("#{ systemProperties['user.region'] }") public void setDefaultLocale(String defaultLocale) { this.defaultLocale = defaultLocale; } public String getDefaultLocale() { return this.defaultLocale; } } ``` #### @Autowired方法和构造器 @Autowired方法和构造器可以使用@Value注解为参数指定默认值: ```java public class SimpleMovieLister { private MovieFinder movieFinder; private String defaultLocale; @Autowired public void configure(MovieFinder movieFinder, @Value("#{ systemProperties['user.region'] }") String defaultLocale) { this.movieFinder = movieFinder; this.defaultLocale = defaultLocale; } // ... } ``` ```java public class MovieRecommender { private String defaultLocale; private CustomerPreferenceDao customerPreferenceDao; public MovieRecommender(CustomerPreferenceDao customerPreferenceDao, @Value("#{systemProperties['user.country']}") String defaultLocale) { this.customerPreferenceDao = customerPreferenceDao; this.defaultLocale = defaultLocale; } // ... } ```