@Autowired 與@Resource的區(qū)別

一、Autowired與Resource基本背景

1、兩者都是用于bean的注入使用

2、@Resource

    默認(rèn)按照byName方式進(jìn)行裝配,屬于J2EE自帶注解,沒(méi)有指定name時(shí),name指的是變量名

   1)如果同時(shí)指定了name和type,則從Spring上下文中找到唯一匹配的bean進(jìn)行裝配,找不到則拋出異常

   2) 如果指定了name,則從上下文中查找名稱(id)匹配的bean進(jìn)行裝配,找不到則拋出異常

   3) 如果指定了type,則從上下文中找到類型匹配的唯一bean進(jìn)行裝配,找不到或者找到多個(gè),都會(huì)拋出異常

   4) 如果既沒(méi)有指定name,又沒(méi)有指定type,則自動(dòng)按照byName方式進(jìn)行裝配;如果沒(méi)有匹配,則回退為一個(gè)原始類型進(jìn)行匹配,如果匹配則自動(dòng)裝配;

3、@Autowired

    默認(rèn)按byType自動(dòng)注入,是Spring的注解

    1)@Autowired默認(rèn)按類型裝配(屬于spring的),默認(rèn)情況下必須要求依賴對(duì)象必須存在,如果要允許null值,可以設(shè)置它的required屬性為false;

    2)@Autowired按類型裝配的過(guò)程中,如果發(fā)現(xiàn)找到多個(gè)bean,則又按照byName方式進(jìn)行比對(duì),如果還有多個(gè),則報(bào)出異常;

二、接口只有一個(gè)實(shí)現(xiàn)類

    在開(kāi)發(fā)過(guò)程中,會(huì)存在@Autowired跟@Resouce混著用的情況。
public interface Animal {
   String talk();
}

//注意:@Service 默認(rèn)value=dog,首字母小寫
@Service
public class Dog implements Animal {
   @Override
   public String talk() {
      return "Dog talk:";
   }
}

@RestController
@Controller(value = "/zoo")
@RequestMapping("/zoo")
public class ZooController {
   @Resource
   Animal animal;

   @GetMapping("/talk")
   public String animalTalk() {
      return animal.talk();
   }
}
    上面用簡(jiǎn)單的代碼示例,演示接口只有一個(gè)實(shí)現(xiàn)類的情況下,使用Resouce注解。

    結(jié)果:顯示正確
image
    改動(dòng),將Resouce改為Autowired,結(jié)果也正常顯示。

    結(jié)論:在接口只有一個(gè)實(shí)現(xiàn)類的時(shí)候,@Autowired跟@Resouce可以替換使用

三、接口有多個(gè)實(shí)現(xiàn)類

    Animal接口,現(xiàn)在有Dog跟Cat兩個(gè)實(shí)現(xiàn)類
@Service
public class Cat implements Animal {
   @Override
   public String talk() {
      return "Cat talk";
   }
}

1、@Resouce注解

運(yùn)行時(shí)會(huì)報(bào)錯(cuò),錯(cuò)誤信息為:


No qualifying bean of type 'cn.woonton.water.demo.Animal' available: expected single matching bean but found 2: cat,dog

由于Resouce優(yōu)先使用name去匹配,找到了2個(gè)實(shí)現(xiàn)類,所以報(bào)出了異常

解決辦法:

1、修改注入的注解,增加name

@RestController
@Controller(value = "/zoo")
@RequestMapping("/zoo")
public class ZooController { 
   @Resource(name = "dog")
   //@Qualifier("dog")
   Animal animal;
    ......
}

再運(yùn)行,正常。

2、修改實(shí)現(xiàn)類的service的value

//@Service 默認(rèn)value=dog,首字母小寫
@Service("animal")
public class Dog implements Animal {
   ......
}

再運(yùn)行,正常。

2、@Autowired注解

IDEA直接提示報(bào)錯(cuò)


![image](https://upload-images.jianshu.io/upload_images/1944843-8d8e2f4fa7e62d78.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

解決辦法:

1、使用@Primary修飾實(shí)現(xiàn)類,告訴Spring,如果有多個(gè)實(shí)現(xiàn)類時(shí),優(yōu)先注入@Primary注解修飾的那個(gè)。

@Primary
@Service
public class Dog implements Animal {
     ......
}

再運(yùn)行,正常。

2、使用@Qualifier注解

@RestController
@Controller(value = "/zoo")
@RequestMapping("/zoo")
public class ZooController {
   @Autowired
   @Qualifier("dog")
   Animal animal;
    ......
}

再運(yùn)行,正常。

四、片尾

byName,這個(gè)name是指類名?還是變量名?

public interface Human {
   String run();
}

@Service
public class Man implements Human {
   @Override
   public String run() {
      return "Man run";
   }
}

新增一個(gè)service,然后修改controller中的變量名

@RestController
@Controller(value = "/zoo")
@RequestMapping("/zoo")
public class ZooController {
   @Resource
   Animal man;
   ......
}

運(yùn)行報(bào)錯(cuò),錯(cuò)誤信息為

Bean named 'man' is expected to be of type 'cn.woonton.water.demo.Animal' but was actually of type 'cn.woonton.water.demo.Man'

抱著嘗試的態(tài)度,發(fā)現(xiàn)此時(shí)的name指的是變量名。所以根據(jù)變量名找到的類跟實(shí)際類不符合,所以報(bào)錯(cuò)了。

最后編輯于
?著作權(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ù)。

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