三種主要裝配方式:
- 自動(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ā)。