Spring 學習筆記(五)執行時注入

weixin_34185364發表於2018-12-16

直接看程式碼示例:

@Bean
public CompactDisc sgtPeppers(){
    return new BlankDisc("Sgt. Pepper's Lonely Hearts Club Bans","The Beatles");
}

這裡的 tittle artist 都是硬編碼的,但有的時候,我們可能會希望避免硬編碼值,而是想讓這些值在執行時再確定。為了實現這些功能,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()方法中,會建立一個新的BlankDisc,它的構造器引數是從屬性檔案中獲取的,而這是通過呼叫getProperty()實現的。
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處於啟用狀態:
-String[] getActiveProfiles():返回啟用profile名稱的陣列;
-String[] getDefaultProfiles():返回預設profile名稱的陣列;
-boolean acceptsProfiles(String... profiles):如果environment支援給定profile的話,就返回true。

屬性佔位符

Spring一直支援將屬性定義到外部的屬性的檔案中,並使用佔位符值將其插入到Spring bean中。在Spring裝配中,佔位符的形式為使用“${.. }”包裝的屬性名稱。作為樣例,我們可以在XML中按照如下的方式解析BlankDisc構造器引數:

<bean id="sgtPeppers" class="soundsystem.BlankDisc" c:_tittle="${disc.title}" c:_artist="${disc.artist}"/>

如果我們依賴於元件掃描和自動裝配來建立和初始化應用元件的話,那麼就沒有指定佔位符的配置檔案或類了。在這種情況下,我們可以使用@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}  //浮點數
#{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 運算子


7155422-b026e4cd47358c25.png
image.png

7155422-d1ff694d6ccb5843.png
image.png
#{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]}

相關文章