Spring SpEL表达式

Spring 3.0创建了一种新的方式用以配置对象的注入(set注入或者构造参数注入),它便是SpEL(Spring Expression Language)。

基础特性

SpEL使用#{…}作为定界符,所有在大框号中的字符都将被认为是SpEL.

字面量的表示

整数
<property name="count" value="#{5}"/>
小数
<property name="frequency" value="#{89.7}"/>   
科学计数法
<property name="capacity" value="#{1e4}"/>   
String可以使用单引号或者双引号作为字符串的定界符号
<property name="name" value="#{'Chuck'}"/>   
<property name='name' value='#{"Chuck"}'/>   
Boolean
<property name="enabled" value="#{false}"/>   

引用Bean,属性和方法

引用其他对象
<bean id=”saxophone” value=”com.xxx.xxx.xxx”/>


<bean ..>
    <property name="instrument" value="#{saxophone}"/>
<bean/>

<!-- 通过id:“saxophone”将对象注入到instrument属性中,这与下面的配置是一样的: --> 

<bean ..>
    <property name="instrument" ref="saxophone"/>   
<bean/>
引用其他对象的属性
<bean id="kenny" class="com.springinaction.springidol.Instrumentalist"/>

<bean id="carl" class="com.springinaction.springidol.Instrumentalist">
    <property name="song" value="#{kenny.song}" />
</bean>   

<!--  kenny是BeanId,而song是属性的名字,这样配置就如同写了如下的java代码: -->
Instrumentalist carl = new Instrumentalist(); 
carl.setSong(kenny.getSong());
调用其他方法
<property name="song" value="songSelector.selectSong()"/>  

<!-- 调用了BeanId为“songSelector”的对象的selectSong()方法,并将返回值
    注入到song属性中。或者还可以链式操作。如下: -->
<property name="song" value="songSelector.selectSong().toUpperCase()"/> 

如果songSelector.selectSong()返回null的还会抛出异常,为了避免我们要使用?.表达式。这样如果songSelector.selectSong()为null就不会再调用后面的方法了。如下:

<property name="song" value="songSelector.selectSong()?.toUpperCase()"/>
调用静态方法

我们已经知道如何通过一个对象调用它的方法了,但是如何调用一个静态方法呢?用T(),它将返回一个 Class object,然后我们再调用相应的属性或方法即可:

<property name="multiplier" value="T(java.lang.Math).PI"/>

SpEL支持的运算符号

算数运算符

+, -, *, /, %, ^

<property name="adjustedAmount" value="#{counter.total + 42}"/>
<property name="adjustedAmount" value="#{counter.total - 20}"/>   
<property name="circumference" 
          value="#{2 * T(java.lang.Math).PI * circle.radius}"/>   
<property name="average" value="#{counter.total / counter.count}"/>
<property name="remainder" value="#{counter.total % counter.count}"/>
<property name="area" 
          value="#{T(java.lang.Math).PI * circle.radius ^ 2}"/>

<!-- 加号还可以用作字符串连接 -->
<property name="fullName" 
          value="#{performer.firstName + ' ' + performer.lastName}"/>  

比较运算符

<, >, ==, <=, >=, 等价文本型比较运算符 lt, gt, eq, le, ge

<property name="equal" value="#{counter.total == 100}"/>

<!-- 不可以使用<和>号,因为在xml中它有特殊的含义,我们使用lt和gt代替 -->
<property name="hasCapacity" value="#{counter.total le 100000}"/>

逻辑运算符

and, or, not, |

<property name="largeCircle" 
          value="#{shape.kind == 'circle' and shape.perimeter gt 100}"/>
<property name="outOfStock" value="#{!product.available}"/>
<property name="outOfStock" value="#{not product.available}"/> 

If-else运算符

?: (ternary), ?: (Elvis)

<!-- 最基本的?:(这如同使用EL表达式语言) -->
<property name="song" 
          value="#{kenny.song != null ? kenny.song : 'Greensleeves'}"/>

<!--变体的?:(与上面紧邻配置等价) -->
<property name="song" value="#{kenny.song ?: 'Greensleeves'}"/>

正则表达式

matches

<!-- 表达式返回逻辑值,如果匹配返回true,否则返回false -->
<property name="validEmail" value="#{admin.email 
    matches '[a-zA-Z0-9._%+-]+@ [a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}'}"/> 

对集合的支持

有如下类:

package com.habuma.spel.cities;

public class City {
    private String name;
    private String state;
    private int population;
}

Xml中有如下定义:

<util:list id="cities">   
<bean class="com.habuma.spel.cities.City"   
    p:name="Chicago" p:state="IL" p:population="2853114"/>
<bean class="com.habuma.spel.cities.City"   
    p:name="Atlanta" p:state="GA" p:population="537958"/>
<bean class="com.habuma.spel.cities.City"   
    p:name="Dallas"  p:state="TX" p:population="1279910"/>
<bean class="com.habuma.spel.cities.City"   
    p:name="Houston" p:state="TX" p:population="2242193"/> 
<bean class="com.habuma.spel.cities.City"   
    p:name="Odessa"  p:state="TX" p:population="90943"/>
<bean class="com.habuma.spel.cities.City"   
    p:name="El Paso" p:state="TX" p:population="613190"/>
<bean class="com.habuma.spel.cities.City"  
    p:name="Jal"     p:state="NM" p:population="1996"/> 
<bean class="com.habuma.spel.cities.City"   
    p:name="Las Cue" p:state="NM" p:population="91865"/>
</util:list>

Spring的p标签是基于XML Schema的配置方式,是命名空间,目的是为了简化配置方式。使用时,需要引入schema,即xmlns:p=”http://www.springframework.org/schema/p”。

<bean id="person" class="com.myclass.Person">
    <property name="age" value="21"/>
    <property name="tool" ref="tool"/>
</bean>

<!-- 使用p标签等价配置: -->
<bean id="person" class="com.myclass.Person" p:age="21" p:tool-ref="tool"/>

获取Collection中的某个对象

通过下标访问,如下:

<property name="chosenCity" value="#{cities[2]}"/>

我们就会获得population为”1279910”的city(记住下标从0开始)

下标可以通过变量指定,如下:

<property name="chosenCity" 
          value="#{cities[T(java.lang.Math).random() * cities.size()]}"/>

如果是从Map中获得,可指定key值,如下:

<property name="chosenCity" value="#{cities['Dallas']}"/>   

也可以通过key访问properties的值,如下:

<util:properties id="settings"      
          location="classpath:settings.properties"/>

<property name="accessToken" 
          value="#{settings['twitter.accessToken']}"/>

可以通过下标访问systemEnvironmentsystemProperties中的值:

<property name="homePath" 
          value="#{systemEnvironment['HOME']}"/>   

如果在jre运行时配置了-Dapplication.home=/etc/myapp,我们可以通过如下方式访问:

<property name="homePath" 
          value="#{systemProperties['application.home']}"/

通过下标获取String串中的某个字符:

'This is a test'[3]

获取Collection中的子集-通过条件筛选

注意:新对象是一个新的Collection

筛选子集(.?[])
<property name="bigCities" 
          value="#{cities.?[population gt 100000]}"/>
获取第一个(.^[])
<property name="aBigCity" 
          value="#{cities.^[population gt 100000]}"/>   
获取最后一个(.$[])
<property name="aBigCity" 
          value="#{cities.$[population gt 100000]}"/> 
集合的投影(.![])

如果想获得所有城市的名称组成的列表,可用如下操作:

<property name="cityNames" value="#{cities.![name]}"/>
<!-- 将返回"Chicago", "Atlanta", "Dallas". 也可以组合两个列,如下:  -->


<property name="cityNames" value="#{cities.![name + ', ' + state]}"/> 
<!-- 将返回"Chicago, IL", "Atlanta, GA", and "Dallas, TX".  --> 

将投影和筛选结合:

<property name="cityNames"
    value="#{cities.?[population gt 100000].![name + ', ' + state]}"/>  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值