天天看點

4. 使用表達式裝配使用表達式裝配

使用表達式裝配

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=]]]