Spring注入Bean的一些方式總結(jié)
通過(guò)注解注入Bean
背景
我們談到Spring的時(shí)候一定會(huì)提到IOC容器、DI依賴注入,Spring通過(guò)將一個(gè)個(gè)類標(biāo)注為Bean的方法注入到IOC容器中,達(dá)到了控制反轉(zhuǎn)的效果。那么我們剛開(kāi)始接觸Bean的時(shí)候,一定是使用xml文件,一個(gè)一個(gè)的注入,就例如下面這樣。
<bean id="bean" class="beandemo.Bean" />
我們的項(xiàng)目一般很大的話,就需要成千上百個(gè)Bean去使用,這樣寫起來(lái)就很繁瑣。那么Spring就幫我們實(shí)現(xiàn)了一種通過(guò)注解來(lái)實(shí)現(xiàn)注入的方法。只需要在你需要注入的類前面加上相應(yīng)的注解,Spring就會(huì)幫助我們掃描到他們?nèi)?shí)現(xiàn)注入。
xml掃描包的方式
<context:component-scan base-package="com.company.beandemo"/>
通過(guò)注解注入的一般形式
一般情況下,注入Bean有一個(gè)最直白,最易懂的方式去實(shí)現(xiàn)注入,下面廢話先不多說(shuō),先貼代碼。
Bean類
public class MyBean{ }
Configuration類
//創(chuàng)建一個(gè)class配置文件 @Configuration public class MyConfiguration{ //將一個(gè)Bean交由Spring進(jìn)行管理 @Bean public MyBean myBean(){ return new MyBean(); } }
Test類
與xml有一點(diǎn)不同,這里在Test中,實(shí)例化的不再是ClassPathXmlApplicationContext,而是獲取的AnnotationConfigApplicationContext實(shí)例。
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class); MyBean myBean = cotext.getBean("myBean",MyBean.class); System.out.println("myBean = " + myBean);
上面的代碼中MyBean也就是我們需要Spring去管理的一個(gè)Bean,他只是一個(gè)簡(jiǎn)單的類。而MyConfiguration中,我們首先用@Configuration注解去標(biāo)記了該類,這樣標(biāo)明該類是一個(gè)Spring的一個(gè)配置類,在加載配置的時(shí)候會(huì)去加載他。
在MyConfiguration中我們可以看到有一個(gè)方法返回的是一個(gè)MyBean的實(shí)例,并且該方法上標(biāo)注著@Bean的注解,標(biāo)明這是一個(gè)注入Bean的方法,會(huì)將下面的返回的Bean注入IOC。
通過(guò)構(gòu)造方法注入Bean
我們?cè)谏梢粋€(gè)Bean實(shí)例的時(shí)候,可以使用Bean的構(gòu)造方法將Bean實(shí)現(xiàn)注入。直接看代碼
Bean類
@Component public class MyBeanConstructor { private AnotherBean anotherBeanConstructor; @Autowired public MyBeanConstructor(AnotherBean anotherBeanConstructor){ this.anotherBeanConstructor = anotherBeanConstructor; } @Override public String toString() { return "MyBean{" + "anotherBeanConstructor=" + anotherBeanConstructor + '}'; } }
AnotherBean類
@Component(value="Bean的id,默認(rèn)為類名小駝峰") public class AnotherBean { }
Configuration類
@Configuration @ComponentScan("com.company.annotationbean") public class MyConfiguration{ }
這里我們可以發(fā)現(xiàn),和一般方式注入的代碼不一樣了,我們來(lái)看看新的注解都是什么意思:
@AutoWired
簡(jiǎn)單粗暴,直接翻譯過(guò)來(lái)的意思就是自動(dòng)裝配:wrench:,還不理解為什么叫自動(dòng)裝配:wrench:?看了下一個(gè)注解的解釋你就知道了。若是在這里注入的時(shí)候指定一個(gè)Bean的id就要使用@Qualifier注解
@Component(默認(rèn)單例模式)
什么??這翻譯過(guò)來(lái)是零件,怎么感覺(jué)像是修汽車??是的,Spring管理Bean的方法就是修汽車的方式。我們?cè)谛枰獙⒁粋€(gè)類變成一個(gè)Bean被Spring可以注入的時(shí)候加上注解零件@Conmonent,那么我們就可以在加載Bean的時(shí)候把他像零件一樣裝配:wrench:到這個(gè)IOC汽車上了
在這里我們還有幾個(gè)其他的注解也可以實(shí)現(xiàn)這個(gè)功能,也就是細(xì)化的@Component:
- @Controller 標(biāo)注在Controller層
- @Service 標(biāo)注在Service層
- @Repository 標(biāo)注在dao層
- @ComponentScan("")
還是翻譯,零件掃描,我們?nèi)タ纯蠢ㄌ?hào)里的“零件倉(cāng)庫(kù)”里面,哪些“零件”(類)需要被裝載,Spring就會(huì)去掃描這個(gè)包,將里面所有標(biāo)注了@Component的類進(jìn)行注入。
這里的通過(guò)構(gòu)造方法進(jìn)行注入就很好理解了,我們?cè)谘b配MyBean這個(gè)零件的時(shí)候,突然發(fā)現(xiàn)他必須在AnotherBean的基礎(chǔ)上才能安裝到IOC里面,那么我們就在每次裝配MyBean的時(shí)候自動(dòng)裝配:wrench:一個(gè)AnotherBean進(jìn)去。舉個(gè):chestnut:吧:
還是以汽車為例,我們?cè)诓扔烷T出發(fā)之前,是不是必須發(fā)車??這里的AutoWired的內(nèi)容就像發(fā)車,你不發(fā)車,這個(gè)油門你踩斷都沒(méi)有用,他都不會(huì)走。
通過(guò)set方法注入Bean
我們可以在一個(gè)屬性的set方法中去將Bean實(shí)現(xiàn)注入,看代碼吧
MyBean類
@Component public class MyBeanSet { private AnotherBean anotherBeanSet; @Autowired public void setAnotherBeanSet(AnotherBean anotherBeanSet) { this.anotherBeanSet = anotherBeanSet; } @Override public String toString() { return "MyBeanSet{" + "anotherBeanSet=" + anotherBeanSet + '}'; } }
Configuration類 和 Test類
同上一個(gè),就不貼了
這里我們發(fā)現(xiàn)在setter方法上我們有一個(gè)@AutoWired,與上面不同的是,我們不會(huì)在實(shí)例化該類時(shí)就自動(dòng)裝配:wrench:這個(gè)對(duì)象,而是在顯式調(diào)用setter的時(shí)候去裝配。
通過(guò)屬性去注入Bean
我們前面兩種注入的方式諸如時(shí)間不同,并且代碼較多,若是通過(guò)屬性,即就是
@Component public class MyBeanProperty { @Autowired private AnotherBean anotherBeanProperty; @Override public String toString() { return "MyBeanProperty{" + "anotherBeanProperty=" + anotherBeanProperty + '}'; } }
這里我們可以看到我們這個(gè)類中需要使用AnotherBean這個(gè)實(shí)例對(duì)象,我們可以通過(guò)@AutoWired去自動(dòng)裝配它。
對(duì)于有些小伙伴問(wèn)私有屬性,Spring怎么去加載它到IOC的?推薦去看看反射
通過(guò)List注入Bean
MyBeanList類
@Component public class MyBeanList { private List<String> stringList; @Autowired public void setStringList(List<String> stringList) { this.stringList = stringList; } public List<String> getStringList() { return stringList; } }
MyConfiguration類
@Configuration @ComponentScan("annoBean.annotationbean") public class MyConfiguration { @Bean public List<String> stringList(){ List<String> stringList = new ArrayList<String>(); stringList.add("List-1"); stringList.add("List-2"); return stringList; } }
這里我們將MyBeanList進(jìn)行了注入,對(duì)List中的元素會(huì)逐一注入。下面介紹另一種方式注入List
MyConfiguration類
@Bean //通過(guò)該注解設(shè)定Bean注入的優(yōu)先級(jí),不一定連續(xù)數(shù)字 @Order(34) public String string1(){ return "String-1"; } @Bean @Order(14) public String string2(){ return "String-2"; }
注入與List中泛型一樣的類型,會(huì)自動(dòng)去匹配類型,及時(shí)這里沒(méi)有任何List的感覺(jué),只是String的類型,但他會(huì)去通過(guò)List的Bean的方式去注入。
第二種方式的優(yōu)先級(jí)高于第一種,當(dāng)兩個(gè)都存在的時(shí)候,若要強(qiáng)制去使用第一種方式,則要去指定Bean的id即可
通過(guò)Map去注入Bean
@Component public class MyBeanMap { private Map<String,Integer> integerMap; public Map<String, Integer> getIntegerMap() { return integerMap; } @Autowired public void setIntegerMap(Map<String, Integer> integerMap) { this.integerMap = integerMap; } }
@Bean public Map<String,Integer> integerMap(){ Map<String,Integer> integerMap = new HashMap<String, Integer>(); integerMap.put("map-1",1); integerMap.put("map-2",2); return integerMap; } @Bean public Integer integer1(){ return 1; } @Bean public Integer integer2(){ return 2; }
同樣這里也具有兩種方式去注入Map類型Bean,且第二種的優(yōu)先值高于第一種
以上就是Bean通過(guò)注解注入的幾種方式,大家可以對(duì)比著xml注入的方式去看。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
- Spring攔截器中注入Bean失敗解放方案詳解
- SpringBoot通過(guò)注解注入Bean的幾種方式解析
- Spring為IOC容器注入Bean的五種方式詳解
- 詳解SpringBoot 多線程處理任務(wù) 無(wú)法@Autowired注入bean問(wèn)題解決
- 解決SpringBoot項(xiàng)目使用多線程處理任務(wù)時(shí)無(wú)法通過(guò)@Autowired注入bean問(wèn)題
- Spring中如何動(dòng)態(tài)注入Bean實(shí)例教程
- Spring 多線程下注入bean問(wèn)題詳解
- Spring為singleton?bean注入prototype?bean
相關(guān)文章
Java實(shí)現(xiàn)定時(shí)任務(wù)的示例代碼
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)定時(shí)任務(wù)的相關(guān)知識(shí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-11-11SpringBoot 如何使用RestTemplate來(lái)調(diào)用接口
這篇文章主要介紹了SpringBoot 如何使用RestTemplate來(lái)調(diào)用接口方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10