使用表達式裝配
SpEL導言
我們前面在配置檔案中,為Bean注入值是在編譯器就已經完成的(可以這麼認為),但是如果為屬性裝配的值要在運作期才能得到,就需要使用表達式來裝配。
Spring 3引入Spring表達式語言SpEL,通過在運作期執行的表達式将值裝配到Bean的屬性或構造器中。
SpEL有許多特性:
- 使用Bean的ID來引用Bean
- 調用方法和通路對象的屬性
- 對值進行算術、關系和邏輯運算
- 正規表達式比對
- 集合操作
SpEL的基本原理
SpEL表達式的首要目标就是通過計算獲得某個值。
1. 字面值
#{}标記提示Spring标記裡的内容是SpEL表達式。
當然,擷取字面值,一般沒有必要使用SpEL表達式,這也不能展現出它的優勢。
2. 引用Bean、Properties和方法
SpEL能通過ID引用其他Bean
<!-- saxophone是一個Bean的id -->
<property name="instrument" value="#{saxophone}"/>
<!--- 等效于 -->
<property name="instrument" ref="saxophone"/>
SpEL可以用Bean的引用來擷取Bean的屬性
<!-- saxophone是一個Bean的id -->
<property name="instrument" value="#{instrumentalist.song}"/>
<!-- 實際上是調用instrumentalist.getSong() -->
SpEL可調用Bean的方法
<!-- songSelect是一個Bean的id -->
<property name="song" value="#{songSelect.selectSong()}"/>
3. 操作類
在SpEL中,使用T()運算符會通路類作用域的方法和常量
T(java.lang.Math)會傳回一個java.lang.Math類對象
T()運算符還可以通路指定類的靜态方法和常量
<property name="pi" value="#{T{java.lang.Math}.PI}"/>
<property name="randomNumber" value="#{T{java.lang.Math}.random()}"/>
4. SpEL提供了幾種運算符,可以用在表達式中的值上
Operation Type | Operators |
---|---|
算術運算 | +,-,*,/,%,^ |
關系運算 | , <, ==, <=, >=, lt, gt, eq, le, ge |
邏輯運算 | and,or,not, |
條件表達式(三目運算符) | ? : |
正規表達式 | matches |
5. 在SpEL中篩選集合
-
通路集合成員
中括号[]運算符通過索引通路集合中的成員,中括号[]同樣可以用來擷取java.util.Map集合中的成員。
-
查詢集合成員
.?[]表示查詢出所有比對項(結果傳回的是一個集合)
<property name=”bigCitys” value=”#{cities.?[population >= 100000]}” />
.^[]表示查詢出第一個比對項(傳回的是一個對象)
<property name=”bigCitys” value=”#{cities.^[population >= 100000]}” />
.$[]表示查詢出最後一個比對項(傳回的是一個對象)
<property name=”bigCitys” value=”#{cities.$[population >= 100000]}” />
-
集合投影·
從集合的每一個成員中選擇特定的屬性放入一個新的集合中。投影運算符:.![]
<property name=”cityNames” value=”#{cities.![name]}” />
示例
City類
package com.li.spring.spel;
public class City {
private String name;
private String state;
private int population;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public int getPopulation() {
return population;
}
public void setPopulation(int population) {
this.population = population;
}
@Override
public String toString() {
return "City [name=" + name + ", state=" + state + ", population=" + population + "]";
}
}
city.xml配置檔案
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引用Spring的多個Schema空間的格式定義檔案 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 要使用util-list元素,需要先在頭部引入util相關的聲明 -->
<bean id="city" class="com.li.spring.spel.City"></bean>
<util:list id="cities">
<!-- Bean的ID省略掉,因為我們可以通過下标通路到而不需要通過ID來通路它們 -->
<bean class="com.li.spring.spel.City" p:name="北京" p:state="北京" p:population="10000"></bean>
<bean class="com.li.spring.spel.City" p:name="上海" p:state="上海" p:population="20000"></bean>
<bean class="com.li.spring.spel.City" p:name="廣州" p:state="廣東" p:population="50000"></bean>
<bean class="com.li.spring.spel.City" p:name="南京" p:state="江蘇" p:population="30000"></bean>
<bean class="com.li.spring.spel.City" p:name="拉薩" p:state="西藏" p:population="10000"></bean>
</util:list>
<bean id="cityTest" class="com.li.spring.spel.CityTest">
<property name="chosenCity" value="#{cities[1]}"></property>
<property name="bigCities" value="#{cities.?[population>=30000]}"></property>
<property name="aBigCity" value="#{cities.^[population>=10000]}"></property>
</bean>
</beans>
測試類
package com.li.spring.spel;
import java.io.File;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CityTest {
private City chosenCity;
private List<City> bigCities;
private List<City> aBigCity;
public City getChosenCity() {
return chosenCity;
}
public void setChosenCity(City chosenCity) {
this.chosenCity = chosenCity;
}
public List<City> getBigCities() {
return bigCities;
}
public void setBigCities(List<City> bigCities) {
this.bigCities = bigCities;
}
public List<City> getaBigCity() {
return aBigCity;
}
public void setaBigCity(List<City> aBigCity) {
this.aBigCity = aBigCity;
}
@Override
public String toString() {
return "CityTest [chosenCity=" + chosenCity + ", bigCities=" + bigCities + ", aBigCity=" + aBigCity + "]";
}
public static void main(String[] args) {
ApplicationContext ctx=new ClassPathXmlApplicationContext("com"+File.separator+"li"+File.separator+"spring"+
File.separator+"spel"+File.separator+"city.xml");
CityTest test=(CityTest) ctx.getBean("cityTest");
System.out.println(test);
}
}
運作結果:
CityTest [chosenCity=City [name=上海, state=上海, population=], bigCities=[City [name=廣州, state=廣東, population=], City [name=南京, state=江蘇, population=]], aBigCity=[City [name=北京, state=北京, population=]]]