一、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ò)

解決辦法:
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ò)了。