轉(zhuǎn)載自:https://mp.weixin.qq.com/s?src=11×tamp=1592840150&ver=2416&signature=H9gO-29hpeUbnh4QLU7g3IRrno9zqxrFD4YpZJEp4eeUFHSpJuukhAqWb3wkboQOyvhkc-oaZ1itqtcRF11glESG4BjCfiEPdFhuvMkJt7y9VX6baUw-WO2bZKDL&new=1
前言
Spring3.0之前要使用Spring必須要有一個(gè)xml配置文件,而Spring3.0之后注解慢慢登上舞臺(tái),通過(guò)注解@Configuration和@Bean可以完全搞定。此時(shí),注解和xml配置形成了相互協(xié)作與競(jìng)爭(zhēng)的關(guān)系。隨著Springboot的推廣,注解的使用在Spring中大放光彩,xml的輝煌一去不返。通過(guò)注解,簡(jiǎn)化了配置,提升了編碼效率。
Spring 3.0新增了另外兩個(gè)實(shí)現(xiàn)類(lèi):AnnotationConfigApplicationContext 和 AnnotationConfigWebApplicationContext。它們是為注解而生,直接依賴(lài)于注解作為容器配置信息來(lái)源的IoC容器初始化類(lèi)。AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的web版本,其用法與后者相比幾乎沒(méi)有什么差別。
今天這篇文章帶大家學(xué)習(xí)@Configuration和@Bean的使用,并通過(guò)具體的實(shí)例體驗(yàn)一下注解的方便快捷。如果你的項(xiàng)目中還未曾使用此類(lèi)注解,說(shuō)明你的技術(shù)棧已經(jīng)在被淘汰的邊緣。
基于Java類(lèi)的配置選項(xiàng)
Spring 3.0引入了注解,配置文件的載體就從xml文件轉(zhuǎn)換為了Java類(lèi),Java類(lèi)就是一個(gè)普通的類(lèi),除了命名建議以“**Config”結(jié)尾方便識(shí)別外,Spring對(duì)其有一定的約定條件。
配置類(lèi)不能是 final 類(lèi)(沒(méi)法動(dòng)態(tài)代理)。
配置類(lèi)必須是非本地的(即不能將配置類(lèi)定義在其他類(lèi)的方法內(nèi)部,不能是private)。
配置類(lèi)必須有一個(gè)無(wú)參構(gòu)造函數(shù)。
基本使用方法
符合上述條件的類(lèi),就可以使用@Configuration來(lái)進(jìn)行注解,表示這個(gè)類(lèi)可以使用Spring IoC容器作為bean定義的來(lái)源。@Bean注解在該類(lèi)的方法上,AnnotationConfigApplicationContext將配置類(lèi)中標(biāo)注了@Bean的方法的返回值識(shí)別為Spring Bean,并注冊(cè)到容器中,歸入IoC容器管理。
@Configuration的作用等價(jià)于XML配置中的標(biāo)簽,@Bean的作用等價(jià)于XML配置中的標(biāo)簽。下面代碼完成了一個(gè)簡(jiǎn)單的示例。
@Configuration加在類(lèi)上,@Bean加在有@Configuration注解的類(lèi)當(dāng)中的特殊方法上,如果某個(gè)對(duì)象想要注入IOC容器當(dāng)中,則將@Bean加在這個(gè)方法上,這個(gè)方法的返回值是要注入的對(duì)象,默認(rèn)注入名是方法名
@Configuration
public class DataSourceConfig{
@Bean
public MysqlDataSource mysqlDataSource(){
return new MysqlDataSource();
}
@Bean(name ="oracleDataSource")
public OracleDataSource oracleDataSource(){
return new OracleDataSource();
}
}
Spring在解析該類(lèi)時(shí),會(huì)識(shí)別出標(biāo)注@Bean的所有方法,執(zhí)行并將方法的返回值(MysqlDataSource和OracleDataSource對(duì)象)注冊(cè)到IoC容器中。默認(rèn)情況下,方法名即為Bean的名字。與以上配置等價(jià)的XML配置如下:
<bean id="mysqlDataSource" class="**.MysqlDataSource"/>
<bean id="oracleDataSource" class="**.OracleDataSource"/>
@Configuration的屬性
@Configuration的定義代碼:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration{
String value() default"";
}
@Configuration注解本身定義時(shí)被@Component標(biāo)注了,因此本質(zhì)上來(lái)說(shuō)@Configuration也是一個(gè)@Component,只不過(guò)我們?cè)诰唧w使用的過(guò)程中基本用不到它的實(shí)例化對(duì)象。
@Bean屬性
@Bean注解的具體代碼定義:
@Target({ElementType.METHOD,ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Bean{
@AliasFor("name")
String[] value() default{};
@AliasFor("value")
String[] name() default{};
Autowire autowire() default Autowire.NO;
String initMethod() default "";
String destroyMethod() default "(inferred)";
}
可以看出@Bean具有以下屬性:
name :指定一個(gè)或者多個(gè)Bean的名字。等價(jià)于XML配置中的name屬性,示例中的@Bean(name = "oracleDataSource")。
initMethod:容器在初始化完Bean之后,會(huì)調(diào)用該屬性指定的方法。等價(jià)于XML配置中的init-method屬性。
destroyMethod:該屬性與initMethod功能相似,在容器銷(xiāo)毀Bean之前,會(huì)調(diào)用該屬性指定的方法。等價(jià)于XML配置中的destroy-method屬性。
autowire:指定Bean屬性的自動(dòng)裝配策略,取值是Autowire類(lèi)型的三個(gè)靜態(tài)屬性。Autowire.BYNAME,Autowire.BYTYPE,Autowire.NO。與XML配置中的autowire屬性的取值相比,少了constructor,因?yàn)?constructor在這里已經(jīng)沒(méi)有意義了。
@Bean默認(rèn)是單例模式,并且沒(méi)有提供指定作用域的屬性,可以通過(guò)@Scope來(lái)實(shí)現(xiàn)該功能。
@Bean
@Scope("prototype")
public MysqlDataSource mysqlDataSource(){
return new MysqlDataSource();
}
Spring掃描加載
當(dāng)配置完Spring掃描指定包及其子包中的類(lèi)時(shí),會(huì)識(shí)別所有標(biāo)記了@Component、@Controller、@Service、@Repository注解的類(lèi),由于@Configuration注解本身也用@Component標(biāo)注了,Spring將能夠識(shí)別出 @Configuration標(biāo)注類(lèi)。