Spring 3引入了Spring表达式语言(Spring Expression Language,SpEL),它能够以一种强大和简洁的方式将值装配到bean属性和构造器参数中,在这个过程中所使用的表达式会在运行时计算得到值。使用SpEL,你可以实现超乎想象的装配效果,这是使用其他的装配技术难以做到的(甚至是不可能的)。
SpEL拥有很多特性:
使用bean的ID来引用bean;
调用方法和访问对象的属性;
对值进行算术、关系和逻辑运算;
正则表达式匹配;
集合操作。
SpEL表达式要放到“#{ ... }”之中,这与属性占位符有些类似,属性占位符需要放到“${ ... }”之中。
#{1} //1
#{T(System).currentTimeMillis()} // 最终结果是计算表达式的那一刻当前时间的毫秒数
除去“#{ ... }”标记之后,剩下的就是SpEL表达式体了,T()表达式 会将java.lang.System视为Java中对应的类型,因此可以调用其static修饰的currentTimeMillis()方法。
- SpEL表达式也可以引用其他的bean或其他bean的属性。例如,如下的表达式会计算得到ID为sgtPeppers的bean的artist属性:
#{sgtPeppers.artist}
- 我们还可以通过systemProperties对象引用系统属性:
#{systemProperties['url']} //获取属性文件的 url 属性
举例:
@Bean("myComponentName03")
public CDPlayer cd(@Value("#{systemProperties['url']}") url,@Value("#{systemProperties['username']}") username,@Value("#{systemProperties['password']}") password) {
return new DataSource(url,username,password));
}
<bean id="customerDAO" class="com.sanxin.org.jdbc.JdbcCustomerDAO"
c:_url = "#{systemProperties['url']}" c:_username = "#{systemProperties['username']}"
c:_password = "#{systemProperties['password']}"/>
SpEL用法规则
- 浮点值:
#{3.141592654}
- 科学记数法的方式进行表示:
#{9.87E4} // 98700
- String类型的字面值:
#{"hello"}
- Boolean类型的值:
#{false}
- 引用bean、属性和方法:
#{sgtPeppers} //通过id引用bean
#{sgtPeppers.artist} //通过id引用bean的属性
#{sgtPeppers.selectArtist()} //通过id引用bean的方法
为了避免出现NullPointerException,我们可以使用类型安全的运算符来操作表达式的内容:
#{sgtPeppers.selectArtist()?.toUpperCase()} //如果selectArtist()的返回值是null的话,那么SpEL将不会调用toUpperCase()方法。表达式的返回值会是null。
- 在表达式中使用类型:
如果要在SpEL中访问类作用域的方法和常量(即static关键字修饰的方法或属性)的话,要依赖T()这个关键的运算符。
T(java.lang.Math).PI //这里所示的T()运算符的结果会是一个Class对象,代表了java.lang.Math。得到PI值
T(java.lang.Math).random() //得到一个0到1之间的随机数
- SpEL运算符:
- 算术运算: + 、 - 、 * 、 / 、 % 、 ^
- 比较运算: < 、 > 、 == 、 <= 、 >= 、 lt 、 gt 、 eq 、 le 、 ge
- 逻辑运算:and 、 or 、 not 、 |
- 条件运算:?: (ternary) 、 ?: (Elvis)
- 正则表达式:matches
当使用String类型的值时,“+”运算符执行的是连接操作,与在Java中是一样的:
#{'我时一个' + sgtPeppers.artist}
要比较两个数字是不是相等,可以使用双等号运算符(==)
#{count.sum == 100} //返回 true 或是 false
#{count.sum eq100} //也可以使用文本型的 eq 运算符
三元运算符,它与Java中的三元运算符非常类似。三元运算符的一个常见场景就是检查null值,并用一个默认值来替代null。例如:
#{user.name ? user.name :'guest'} // 如果是null的话,那么表达式的计算结果就会是“Rattleand Hum”
- 计算正则表达式
#{user.phone matches '[正则表达式]'} //返回true or false
- 计算集合
#{user.cart[4].goodName} // cart时ID为user的bean中的一个集合,goodName是cart集合中对象的属性
“[]”运算符用来从集合或数组中按照索引获取元素,实际上,它还可以从String中获取一个字符。比如:
#{'hello'[1]} //e
- 查询运算符(.?[]),它会用来对集合进行过滤,得到集合的一个子集。
#{user.cart.?[goodName eq '超炫酷']} //挑选出ID为user的bean中cart集合中对象属性goodName为超炫酷的对象。
SpEL还提供了另外两个查询运算符:(.^[])和(.$[]),它们分别用来在集合中查询第一个匹配项和最后一个匹配项。
SpEL还提供了投影运算符(.![]),它会从集合的每个成员中选择特定的属性放到另外一个集合中。假设我们不想要歌曲对象的集合,而是所有歌曲名称的集合,就可以使用投影运算符。