高級裝配

本節(jié)的主要內(nèi)容是:

  • Spring profile
  • 條件化的bean聲明
  • 自動裝配與歧義性
  • bean的作用域
  • 運行時值注入
    本節(jié)內(nèi)容,并不會全部講的非常細疼鸟,因為有的開發(fā)中,由于開發(fā)進度的限制庙曙,可能并不會采用空镜,這里只提供一引子,起到拋磚迎玉的作用捌朴。在遇到的時候吴攒,可以參考往正確的方向?qū)崿F(xiàn)。

一砂蔽、環(huán)境與profile

開發(fā)階段中洼怔,某些環(huán)境相關(guān)做法可能并不適合遷移到生產(chǎn)環(huán)境中,甚至即便遷移過去也無法正常工作左驾。數(shù)據(jù)庫配置镣隶、加密算法以及與外部系統(tǒng)的集成是跨環(huán)境部署時會發(fā)生變化。比如诡右,在不同的開發(fā)環(huán)境安岂,會使用嵌入式數(shù)據(jù)庫,這時候可能就需要用到配置profile bean來解決不同環(huán)境下運行不同嵌入式數(shù)據(jù)庫的問題帆吻。
可以使用@Profile注解域那,在Spring 3.1中,只能在類級別上使用@Profile注解猜煮。不過琉雳,從Spring 3.2開始样眠,你也可以在方法級別上使用@Profile注解,與@Bean注解一同使用翠肘。

二、條件化的bean

假設(shè)你希望一個或多個bean只有在應(yīng)用的類路徑下包含特定的庫時才創(chuàng)建辫秧。Spring 4引入了一個新的@Conditional注解束倍,它可以用到帶有@Bean注解的方法上。如果給定的條件計算結(jié)果為true盟戏,就會創(chuàng)建這個bean绪妹,否則的話,這個bean會被忽略柿究。

三邮旷、處理自動裝配@Autowired 的歧義性

僅有一個bean匹配所需的結(jié)果時,自動裝配才是有效的蝇摸。如果不僅有一個bean能夠匹配結(jié)果的話婶肩,這種歧義性會阻礙Spring自動裝配屬性、構(gòu)造器參數(shù)或方法參數(shù)貌夕。

假設(shè)我們使用@Autowired注解標(biāo)注了構(gòu)造函數(shù)CDPlayer 如下:

    @Autowired 
    public CDPlayer cd(ICompactDisc cd2) {
        this.cd2 = cd2;
    }

這時候有好幾個類都實現(xiàn)了ICompactDisc接口律歼,并將他們創(chuàng)建為Spring應(yīng)用上下文里面的bean

@Component("myComponentName01")
public class CompactDiscImpl01 implements ICompactDisc{
    ...
}

@Component("myComponentName02")
public class CompactDiscImpl01 implements ICompactDisc{
    ...
}

@Component("myComponentName03")
public class CompactDiscImpl01 implements ICompactDisc{
    ...
}

這種情況下CDPlayer 類里面的自動裝配,就會拋錯了啡专。那么怎么解決呢险毁?

  • 標(biāo)示首選的bean,使用@Primary注解们童,@Primary能夠與@Component組合用在組件掃描的bean上畔况,也可以與@Bean組合用在Java配置的bean聲明中。xml配置文件可以在<bean>元素有一個primary屬性用來指定首選的bean慧库,boolean類型
@Component("myComponentName01")
@Primary
public class CompactDiscImpl01 implements ICompactDisc{
    ...
}
<bean id="customerDAO" class="com.sanxin.org.jdbc.JdbcCustomerDAO" primary = "true">
        <property name="dataSource" ref="dataSource" />
</bean>

如果有兩個繼承類跷跪,都同時用了@Primary注解呢,這時候又會拋錯了完沪,因為程序又不知道該使用哪個了域庇。接下來看下面的限定自動裝配的bean來解決這個問題。

  • 限定自動裝配的bean覆积,@Qualifier注解是使用限定符的主要方式听皿。它可以與@Autowired和@Inject協(xié)同使用,在注入的時候指定想要注入進去的是哪個bean宽档。也可以與@Component組合使用尉姨,為bean設(shè)置自己的限定符。
@Component("myComponentName01")
@Qualifier("CompactDiscImpl01 ")
public class CompactDiscImpl01 implements ICompactDisc{
    ...
}
    @Autowired 
    @Qualifier("CompactDiscImpl01 ")
    public CDPlayer cd(ICompactDisc cd2) {
        this.cd2 = cd2;
    }

四吗冤、bean的作用域

在默認情況下又厉,Spring應(yīng)用上下文中所有bean都是作為以單例(singleton)的形式創(chuàng)建的九府。也就是說,不管給定的一個bean被注入到其他bean多少次覆致,每次所注入的都是同一個實例侄旬。

Spring定義了多種作用域,可以基于這些作用域創(chuàng)建bean煌妈,包括:

  • 單例(Singleton):在整個應(yīng)用中儡羔,只創(chuàng)建bean的一個實例。
  • 原型(Prototype):每次注入或者通過Spring應(yīng)用上下文獲取的時候璧诵,都會創(chuàng)建一個新的bean實例汰蜘。
  • 會話(Session):在Web應(yīng)用中,為每個會話創(chuàng)建一個bean實例之宿。
  • 請求(Rquest):在Web應(yīng)用中族操,為每個請求創(chuàng)建一個bean實例。

1.使用@Scope注解比被,它可以與@Component或@Bean一起使用色难。

@Component("myComponentName03")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)  //ConfigurableBeanFactory.SCOPE_PROTOTYPE ="prototype"
public class CompactDiscImpl01 implements ICompactDisc{
    ...
}

也可以在xml文件中配置:

<bean id="customerDAO" class="com.sanxin.org.jdbc.JdbcCustomerDAO" primary = "true" scope="prototype" />

2.以上是使用單例或是原型作用域的方式,那么姐赡,怎么實現(xiàn)使用會話和請求作用域
會話和請求作用域直到某個用戶進入系統(tǒng)莱预,創(chuàng)建了會話之后,才會出現(xiàn)bean實例项滑。

    @Bean("myComponentName03")
    @Scope(value = WebApplicationContext.SCOPE_SESSION,proxyMode=ScopedProxyMode.INTERFACES) 
    public CDPlayer cd(ICompactDisc cd2) {
        this.cd2 = cd2;
    }
<bean id="customerDAO" class="com.sanxin.org.jdbc.JdbcCustomerDAO" primary = "true" scope="prototype" >
      <!-- 默認情況下依沮,它會使用CGLib創(chuàng)建目標(biāo)類的代理。 但是我們也可以將proxy-target-class屬性設(shè)置為false枪狂,進而要求它生成基于接口的代理-->
      <aop:scoped-proxy  proxy-target-class = "false"/>
</bean>

當(dāng)ICompactDisc 時一個借口時危喉,proxyMode屬性被設(shè)置成了ScopedProxyMode.INTERFACES,這表明這個代理要實現(xiàn)ShoppingCart接口州疾,并將調(diào)用委托給實現(xiàn)bean辜限。但如果ShoppingCart是一個具體的類的話,Spring就沒有辦法創(chuàng)建基于接口的代理了严蓖。此時薄嫡,它必須使用CGLib
來生成基于類的代理。所以颗胡,如果bean類型是具體類的話毫深,我們必須要將proxyMode屬性設(shè)置為ScopedProxyMode.TARGET_CLASS,以此來表明要以生成目標(biāo)類擴展的方式創(chuàng)建代理毒姨。

五哑蔫、運行時值注入

Spring提供了兩種在運行時求值的方式:

  • Spring表達式語言(SpEL)。
  • 屬性占位符(Property placeholder)。

1.先看占位符闸迷,下面一個例子嵌纲,將屬性文件jdbc.properties中的值讀取出來,并設(shè)置到DataSource這個類當(dāng)中腥沽。如下代碼:

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;

import com.df.test.pojo.DataSource;
import com.df.test.service.StudentService;

@Configuration
@PropertySource("classpath:jdbc.properties")
public class StudentServiceImpl implements StudentService {
    
    @Autowired
    Environment ev;     

    @Bean
    public DataSource ds(){
        return new DataSource(ev.getProperty("url"),
                ev.getProperty("username"),ev.getProperty("password"));
    }
}

如果我們依賴于組件掃描和自動裝配來創(chuàng)建和初始化應(yīng)用組件的話逮走,那么就沒有指定占位符的配置文件或類了。在這種情況下巡球,我們可以使用@Value注解言沐。

    @Bean("myComponentName03")
    public CDPlayer  cd(@Value("url") url,@Value("username") username,@Value("password") password) {
        return new DataSource(url,username,password));
    }

2.Spring表達式語言(SpEL)。
SpEL擁有很多特性:

  • 使用bean的ID來引用bean酣栈;
  • 調(diào)用方法和訪問對象的屬性;
  • 對值進行算術(shù)汹押、關(guān)系和邏輯運算矿筝;
  • 正則表達式匹配;
  • 集合操作棚贾。

這里就不在細細分析了窖维,可以移步Spring表達式語言(SpEL)學(xué)習(xí)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妙痹,一起剝皮案震驚了整個濱河市铸史,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌怯伊,老刑警劉巖琳轿,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異耿芹,居然都是意外死亡崭篡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門吧秕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來琉闪,“玉大人,你說我怎么就攤上這事砸彬〉弑校” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵砂碉,是天一觀的道長蛀蜜。 經(jīng)常有香客問我,道長绽淘,這世上最難降的妖魔是什么涵防? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上壮池,老公的妹妹穿的比我還像新娘偏瓤。我一直安慰自己,他們只是感情好椰憋,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布厅克。 她就那樣靜靜地躺著,像睡著了一般橙依。 火紅的嫁衣襯著肌膚如雪证舟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天窗骑,我揣著相機與錄音女责,去河邊找鬼。 笑死创译,一個胖子當(dāng)著我的面吹牛抵知,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播软族,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼刷喜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了立砸?” 一聲冷哼從身側(cè)響起掖疮,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颗祝,沒想到半個月后浊闪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡吐葵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年规揪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片温峭。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡猛铅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出凤藏,到底是詐尸還是另有隱情奸忽,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布揖庄,位于F島的核電站栗菜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蹄梢。R本人自食惡果不足惜疙筹,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧而咆,春花似錦霍比、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至涯捻,卻和暖如春浅妆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背障癌。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工凌外, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涛浙。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓趴乡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蝗拿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容