Spring bean的裝配

三種主要裝配方式:
  • 自動(dòng)化配置
  • 基于Java的顯示配置
  • 基于XML的顯示配置
    對(duì)比了三種配置,覺得工作中應(yīng)盡可能使用自動(dòng)化配置,避免顯示配置所帶來的維護(hù)成本。 如果確實(shí)需要顯示配置,優(yōu)先Java配置,比XML配置更強(qiáng)大,類型更安全且易于重構(gòu)。
profile的激活

Spring在確定哪個(gè)profile處于激活狀態(tài)時(shí),需要依賴兩個(gè)獨(dú)立屬性:
spring.profiles.active和spring.profiles.default。
有多重方法設(shè)置這兩種屬性:

  • DispatcherServlet的參數(shù)
  • Web應(yīng)用的上下文參數(shù)
  • JNDI條目
  • 環(huán)境變量
  • JVM系統(tǒng)屬性
  • 集成測(cè)試類中用@ActiveProfile設(shè)置
    從Spring 4 開始,@Profile注解進(jìn)行了重構(gòu),使其基于@Conditional和Condition實(shí)現(xiàn)。實(shí)現(xiàn)見“Spring bean 相關(guān)Annotation收集整理”
處理自動(dòng)裝配的歧義性

如果不僅有一個(gè)bean能夠匹配結(jié)果,歧義性會(huì)阻礙Spring自動(dòng)裝配屬性、構(gòu)造器參數(shù)或方法參數(shù)。比如用@Autowired標(biāo)注了某個(gè)X的set方法,而X是一個(gè)有3個(gè)實(shí)現(xiàn)類的接口,且這三個(gè)類均使用了@Component注解。此時(shí)Spring會(huì)拋出NoUniqueBeanDefinitionException。

解決辦法:
1)標(biāo)示首選的Bean,通過@Primary。(同一接口下只能有一個(gè)Primary bean)
2)使用限定符

  • @Qualifier("classname"),classname可以為自定義的限定符,而不是依賴于將beanID作為限定符。
  • 使用自定義的限定符注解:
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD,
           ElmentType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface YourAnnotation{ }

然后,

@Autowired
@Qualifier("自定義限定符名")
@YourAnnotation
public void setAA(AA aa){
  this.aa = aa;
}
Bean的作用域

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

  • 單例(Singleton):在整個(gè)應(yīng)用中,只創(chuàng)建bean的一個(gè)實(shí)例。
  • 原型(Prototype):每次注入或通過Spring應(yīng)用上下文獲取時(shí),都會(huì)創(chuàng)建一個(gè)新的bean實(shí)例。
  • 會(huì)話(Session):在Web應(yīng)用中,為每個(gè)會(huì)話創(chuàng)建一個(gè)bean實(shí)例。
  • 請(qǐng)求(Rquest):在Web應(yīng)用中,為每個(gè)請(qǐng)求創(chuàng)建一個(gè)bean實(shí)例。
    單例為默認(rèn)作用域,但對(duì)于易變的類型不合適。如果選擇其他的作用域,要使用@Scope注解,可以與@Component@Bean一起使用。
在運(yùn)行時(shí)值注入

有時(shí),我們可能會(huì)希望避免硬編碼值,并讓這些值在運(yùn)行時(shí)再確定。Spring有兩種在運(yùn)行時(shí)求值的方式:

  • 屬性占位符(Property placeholder)
  • Spring表達(dá)式語(yǔ)言(SpEL)
注入外部的值

使用外部屬性來裝配一個(gè)bean:

@Configuration
@PropertySource("classpath:/路徑/app.properties") //聲明屬性源
public class ExpressiveConfig{

  @Autowired
  Environment env;
  @Bean
  public XX x(){
    return new XX(
        env.getProperty("x.title"),
          env.getProperty("x.artist"));
  }
}

在本例中,@PropertySource引用了類路徑中名為app.properties的文件。大致如下所示:

x.title = xxxxx
x.artist = xxxax

這個(gè)屬性的文件會(huì)加載到Spring的Environment中,稍后可以從這里檢索屬性。同時(shí),在x()中,會(huì)創(chuàng)建一個(gè)新的XX,他的構(gòu)造器參數(shù)是從屬性文件中獲取的,而這時(shí)通過調(diào)用getProperty()實(shí)現(xiàn)的。

解析屬性占位符

Spring支持將屬性定義到外部的屬性文件,并使用占位符值將其插入到Spring bean中。在Spring裝配中,占位符的形式為使用${...}包裝屬性名稱。

使用SpEL進(jìn)行裝配

SpEL(Spring Expression Languae)是Spring3引入的一種強(qiáng)大簡(jiǎn)潔的將值裝配到bean屬性和構(gòu)造器參數(shù)中的方式。
SpELl特性:

  • 使用bean的id引用bean;
  • 調(diào)用方法和訪問對(duì)象的屬性;
  • 對(duì)值進(jìn)行算術(shù)、關(guān)系和邏輯運(yùn)算;
  • 正則表達(dá)式匹配;
  • 集合操作。

SpEL需要放入“#{...}”之中。
SpEL表達(dá)式可以引用其他的bean或其他bean的屬性:
#{id.attributename}
與@Value結(jié)合:

public ClassName{
  @Value("#{systemProperties['id.attributename']}") String attributename,
  @Value("#{systemProperties['id.anotherattributename']}") String anotherattributename){
    this.attributename= attributename;
    this.anotherattributename= anotherattributename;
  }

還有很多其他功能,有機(jī)會(huì)整理一篇具體功能再發(fā)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,711評(píng)論 19 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,290評(píng)論 6 342
  • 本章內(nèi)容: Spring profile 條件化的bean聲明 自動(dòng)裝配與歧義性 bean的作用域 Spring表...
    謝隨安閱讀 1,262評(píng)論 0 5
  • 豬,全身是寶。我最愛的是豬油。 印象里對(duì)于豬油的最早記憶來自尤金關(guān)于豬油粕的描述。乍一讀完,就興沖沖地黏著外婆去菜...
    圓滾滾的Isabelle閱讀 479評(píng)論 0 0
  • 今天我把作業(yè)早早的寫完啦!媽媽說要回姥姥家了,我和哥哥高興的答應(yīng)了,媽媽說下午3點(diǎn)就開始出發(fā),我說好啊!我和媽媽去...
    榮瀟瑜閱讀 174評(píng)論 0 0

友情鏈接更多精彩內(nèi)容