直接看代碼示例:
@Bean
public CompactDisc sgtPeppers(){
return new BlankDisc("Sgt. Pepper's Lonely Hearts Club Bans","The Beatles");
}
這里的 tittle artist 都是硬編碼的,但有的時候窿给,我們可能會希望避免硬編碼值贵白,而是想讓這些值在運行時再確定。為了實現(xiàn)這些功能崩泡,Spring提供了兩種在運行時求值的方式:
-屬性占位符(Property placeholder)禁荒。
-Spring表達式語言(SpEL)。
注入外部的值
//程序清單3.7 使用@PropertySource 注解和Environment
package com.soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
@Configuration
@PropertySource("classpath:/com/soundsystem/app.properties")
public class ExpressiveConfig{
@Autowired
Environment
@Bean
public BlankDisc disc(){
return new BlankDisc(env.getProperty("disc.title"),env.getProperty("disc.artist");
}
}
在本例中角撞,@PropertySource引用了類路徑中一個名為app.properties的文件呛伴。定義了 title 和 artist,這個屬性會加載到 spring 的 Environment 中谒所,稍后可以從這里檢索屬性热康。同時,在disc()方法中劣领,會創(chuàng)建一個新的BlankDisc姐军,它的構造器參數(shù)是從屬性文件中獲取的,而這是通過調用getProperty()實現(xiàn)的尖淘。
getProperty()方法并不是獲取屬性值的唯一方法奕锌,getProperty()方法有四個重載的變種形式:
String getProperty(String key)
String getProperty(String key, String defaultValue)
T getProperty(String key, Class<T> type)
T getProperty(String key, Class<T> type, T defaultValue)
Environment還提供了幾個與屬性相關的方法,如果你在使用getProperty()方法的時候沒有指定默認值村生,并且這個屬性沒有定義的話惊暴,獲取到的值是null。如果你希望這個屬性必須要定義趁桃,那么可以使用getRequiredProperty()方法辽话,如下所示:
@Bean
public BlankDisc disc(){
return new BlankDisc(env.getRequireProperty("disc.tltle"),
env.getRequireProperty("disc.artist"));
}
在這里,如果disc.title或disc.artist屬性沒有定義的話镇辉,將會拋出IllegalStateException異常屡穗。
如果想檢查一下某個屬性是否存在的話,那么可以調用Environment的containsProperty()方法:
boolean titleExists = env.containsProperty{"disc.title"};
最后忽肛,如果想將屬性解析為類的話村砂,可以使用getPropertyAsClass()方法:
Class<CompactDisc> cdClass = enc.getPropertyAsClass("disc.class",CompactDisc.class);
除了屬性相關的功能以外,Environment還提供了一些方法來檢查哪些profile處于激活狀態(tài):
-String[] getActiveProfiles():返回激活profile名稱的數(shù)組屹逛;
-String[] getDefaultProfiles():返回默認profile名稱的數(shù)組础废;
-boolean acceptsProfiles(String... profiles):如果environment支持給定profile的話汛骂,就返回true。
屬性占位符
Spring一直支持將屬性定義到外部的屬性的文件中评腺,并使用占位符值將其插入到Spring bean中帘瞭。在Spring裝配中,占位符的形式為使用“${.. }”包裝的屬性名稱蒿讥。作為樣例蝶念,我們可以在XML中按照如下的方式解析BlankDisc構造器參數(shù):
<bean id="sgtPeppers" class="soundsystem.BlankDisc" c:_tittle="${disc.title}" c:_artist="${disc.artist}"/>
如果我們依賴于組件掃描和自動裝配來創(chuàng)建和初始化應用組件的話,那么就沒有指定占位符的配置文件或類了芋绸。在這種情況下媒殉,我們可以使用@Value注解,它的使用方式與@Autowired注解非常相似摔敛。比如廷蓉,在BlankDisc類中,構造器可以改成如下所示:
public BlankDisc(@Value("${disc.title}") String title, @Value("${disc.artist}") String artist){
this.title = title;
this.artist = artist;
}
為了使用占位符马昙,我們必須要配置一個PropertyPlaceholderConfigurer bean或PropertySourcesPlaceholderConfigurer bean桃犬。從Spring3.1開始,推薦使用PropertySourcesPlaceholderConfigurer行楞,因為它能夠基于Spring Environment及其屬性源來解析占位符攒暇。如下的@Bean方法在Java中配置了PropertySourcesPlaceholderConfigurer:
@Bean
public static PropertySourcePlaceholderConfigurer placeholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
如果你想使用XML配置的話,Spring context命名空間中的<context:propertyplaceholder>元素將會為你生成PropertySourcesPlaceholderConfigurer bean
使用Spring表達式語言進行裝配
Spring 3引入了Spring表達式語言(Spring Expression Language子房,SpEL)SpEL擁有很多特性扯饶,包括:
-使用bean的ID來引用bean;
-調用方法和訪問對象的屬性池颈;
-對值進行算術、關系和邏輯運算钓丰;
-正則表達式匹配躯砰;
-集合操作。
SpEL 樣例
SpEL 表達式要放在 “#{ ... }” 之中携丁。
表示字面量
#{3.14159} //浮點數(shù)
#{9.87E4} //科學技術法
#{'Hello'} //String
#{false} //布爾值
引用 bean琢歇、屬性和方法。
#{sgtPeppers} //引用 bean
#{sgtPeppers.artist} //引用 bean 的一個屬性
#{artistSelect.selectArtist()} //調用方法
#{artistSelect.selectArtist().toUpperCase()} //改為大寫字母
在表達式中使用類型
T{java.lang.Math}
T{java.lang.Math}.random()
SpEL 運算符
#{2 * T(java.lang.Math).PI * circle.radius}
#{scoreboard.score > 1000 ? "Winner!" : "Loser"}
計算正則表達式
#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.com'}
計算集合
#{jukebow.songs[4].title}
#{'This is a test'[3]} //表示 string 中第四個
//SpEL 提供了查詢運算符 (.?[])
#{jukebox.songs.?[artist eq 'Aerosmith']}
//SpEL 還提供了 (.^[]) (.$[]) 分別用來在集合中查找第一個和最后一個匹配項
#{jukebox.songs.^[artist eq 'Aerosmith']}
//SpEl 提供了投影運算符 (.![]) 從集合中選擇特定的屬性放到另一個集合中
#{jukebox.songs.![title]}