Spring的@Autowired加到接口上但獲取的是實(shí)現(xiàn)類的問(wèn)題
@Autowired加到接口上但獲取的是實(shí)現(xiàn)類
問(wèn)題
Spring的@Autowired加到接口上但獲取的是實(shí)現(xiàn)類?
?? ?/* 類 @Controller注解,會(huì)在spring容器中實(shí)例化對(duì)象 */
?? ?@Controller
?? ?public class UserContoller{
?? ??? ?@Autowired?? ??? ?// 先按類型找,然后按id為屬性名去找
?? ??? ?private UserService userService;
?? ??? ?//為什么他會(huì)拿到userServiceImpl?
?? ??? ?// @Autowired會(huì)幫你按UserService的類型去容器中找唯一bean對(duì)象
?? ??? ?// 1、容器沒(méi)有該類型的對(duì)象:報(bào)錯(cuò)
?? ??? ?// 2、容器中有該類型的唯一bean對(duì)象,就將該唯一bean對(duì)象賦值給該屬性
?? ??? ?///3、容器中有多個(gè)【兩個(gè)及以上】該類型的唯一bean對(duì)象,
?? ??? ?// ? ? 它會(huì)再根據(jù)該屬性名去容器中找,
?? ??? ?// ? ? 看看容器中的哪個(gè)bean對(duì)象的id值和該屬性名一致,
?? ??? ?// ? ? 如果有,就將容器中該對(duì)象賦值給該屬性,如果沒(méi)有報(bào)錯(cuò)。
?? ?}?? ?
?? ?/* 接口 ?*/
?? ?public interface UserService{}
?? ?
?? ?/* 類 ?@Service注解,會(huì)在spring容器中實(shí)例化對(duì)象 */
?? ?@Service
?? ?public class UserServiceImpl implements UserService{}為什么他會(huì)拿到userServiceImpl?
@Autowired先按類型找,然后再按id為屬性名去找
他會(huì)幫你按UserService的類型去容器中找唯一bean對(duì)象
- 1.容器沒(méi)有該類型的對(duì)象:報(bào)錯(cuò)
- 2.容器中有該類型的唯一bean對(duì)象,就將該唯一bean對(duì)象賦值給該屬性
- 3.容器中有多個(gè)【兩個(gè)及以上】該類型的唯一bean對(duì)象,
它會(huì)再根據(jù)該屬性名去容器中找,看看容器中的哪個(gè)bean對(duì)象的id值和該屬性名一致,如果有,就將容器中該對(duì)象賦值給該屬性,如果沒(méi)有報(bào)錯(cuò)。
然后通過(guò)多態(tài)的向上轉(zhuǎn)型就賦值成功。等價(jià)于之前手動(dòng)賦值
UserService userService = new UserServiceImpl();
@Autowired一個(gè)接口有多個(gè)實(shí)現(xiàn)類
@Autowired是spring的注解,默認(rèn)使用的是byType的方式向Bean里面注入相應(yīng)的Bean。
例如
@Autowired private UserService userService;
這段代碼會(huì)在初始化的時(shí)候,在spring容器中尋找一個(gè)類型為UserService的bean實(shí)體注入,關(guān)聯(lián)到userService的引入上。
但是如果UserService這個(gè)接口存在多個(gè)實(shí)現(xiàn)類的時(shí)候,就會(huì)在spring注入的時(shí)候報(bào)錯(cuò),具體如下:
public class UserService1 implements UserService public class UserService2 implements UserService
當(dāng)存多個(gè)UserService的實(shí)現(xiàn)類時(shí),錯(cuò)誤信息如下:
2016-08-05 14:53:53,795 ERROR [org.springframework.test.context.TestContextManager] - <Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@14a2f921] to prepare test instance [UserServiceTest@3c87521]>
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'UserServiceTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private yjc.demo.service.UserService UserServiceTest.userService; nested exception is he[yjc.demo.service.UserService] is defined: expected single matching bean but found 2: userService1,userService2
拋出了org.springframework.beans.factory.BeanCreationException,而原因是注入的時(shí)候發(fā)現(xiàn)有2個(gè)匹配的bean,但是不知道要注入哪一個(gè):expected single matching bean but found 2: userService1,userService2
那么如何應(yīng)對(duì)多個(gè)實(shí)現(xiàn)類的場(chǎng)景呢,看一下代碼:
@Autowired
private UserService userService1;
?
@Autowired
private UserService userService2;
?
@Autowired
@Qualifier(value = "userService2")
private UserService userService3;
?
@Test
public void test(){
? ? ? ? ?System.out.println(userService1.getClass().toString());
? ? ? ? ?System.out.println(userService2.getClass().toString());
? ? ? ? ?System.out.println(userService3.getClass().toString());
}運(yùn)行結(jié)果:
class yjc.demo.serviceImpl.UserService1
class yjc.demo.serviceImpl.UserService2
class yjc.demo.serviceImpl.UserService2
運(yùn)行結(jié)果成功,說(shuō)明了2種處理多個(gè)實(shí)現(xiàn)類的方法:
1.變量名用userService1,userService2,而不是userService。
通常情況下@Autowired是通過(guò)byType的方法注入的,可是在多個(gè)實(shí)現(xiàn)類的時(shí)候,byType的方式不再是唯一,而需要通過(guò)byName的方式來(lái)注入,而這個(gè)name默認(rèn)就是根據(jù)變量名來(lái)的。
2.通過(guò)@Qualifier注解來(lái)指明使用哪一個(gè)實(shí)現(xiàn)類,實(shí)際上也是通過(guò)byName的方式實(shí)現(xiàn)。
由此看來(lái),@Autowired注解到底使用byType還是byName,其實(shí)是存在一定策略的,也就是有優(yōu)先級(jí)。優(yōu)先用byType,而后是byName。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
XML Web 服務(wù) Eclipse實(shí)現(xiàn)sun-jaxws.xml文件的方法
在sun-jaxws.xml文件,可以配置endpoint、handler-chain等內(nèi)容,在這個(gè)文件中配置的內(nèi)容會(huì)覆蓋在Java代碼中使用注解屬性配置的的內(nèi)容,本文給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2023-11-11
Java使用正則表達(dá)式判斷獨(dú)立字符的存在(代碼示例)
通過(guò)使用正則表達(dá)式,我們可以更加靈活地判斷字符串中是否包含特定的字符,并且可以控制匹配的條件,如獨(dú)立的字符,這為我們處理字符串提供了更多的選擇和功能,這篇文章主要介紹了Java使用正則表達(dá)式判斷獨(dú)立字符的存在,需要的朋友可以參考下2023-10-10
詳解Spring Security 中的四種權(quán)限控制方式
這篇文章主要介紹了詳解Spring Security 中的四種權(quán)限控制方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
springboot 實(shí)現(xiàn)bean手動(dòng)注入操作
這篇文章主要介紹了springboot 實(shí)現(xiàn)bean手動(dòng)注入操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01
設(shè)置Myeclipse中的代碼格式化、注釋模板及保存時(shí)自動(dòng)格式化
這篇文章主要介紹了設(shè)置Myeclipse中的代碼格式化、注釋模板及保存時(shí)自動(dòng)格式化方法,需要的朋友可以參考下2014-10-10
SpringBoot整合SpringSecurityOauth2實(shí)現(xiàn)鑒權(quán)動(dòng)態(tài)權(quán)限問(wèn)題
這篇文章主要介紹了SpringBoot整合SpringSecurityOauth2實(shí)現(xiàn)鑒權(quán)-動(dòng)態(tài)權(quán)限,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06
springboot 返回json格式數(shù)據(jù)時(shí)間格式配置方式
這篇文章主要介紹了springboot 返回json格式數(shù)據(jù)時(shí)間格式配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Java開(kāi)發(fā)druid數(shù)據(jù)連接池maven方式簡(jiǎn)易配置流程示例
本篇文章主要為大家介紹了java開(kāi)發(fā)中druid數(shù)據(jù)連接池maven方式的簡(jiǎn)易配置流程示例,文中附含詳細(xì)的代碼示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助2021-10-10

