前言
由于在工作中遇到了這樣的問題价捧,所以隨筆寫下來饭耳,記錄一下偶垮。
我們平常習(xí)慣的注入方式是:
@Autowired
private 類的名稱 對象名稱;
這種方式是最簡單的遗增,也是最實(shí)用的叫惊。但是有些時(shí)候我們就需要將實(shí)現(xiàn)了同樣接口的Bean注入到Context中,然后可以用 List / Map 接受注入的對象贡定。
正文
想象一下這樣的例子赋访,我們需要解析一個(gè)字符串,有好幾個(gè)解析這個(gè)字符串的Service,然后在對贏得地方使用對應(yīng)的Service蚓耽。如果我們把每一個(gè)解析器Service都有一個(gè)自己的接口渠牲,那么就違背了,他們都在做同一件事步悠,只是做法不同的初衷签杈。如果是有默認(rèn)解析器,可以使用@Primary注解(這個(gè)注解會在實(shí)現(xiàn)相同接口的Bean中找到有@Primary鼎兽,把這個(gè)Bean作為優(yōu)先級最高的注入進(jìn)來)答姥,如果有好多個(gè)@Primary, Spring 又會傻傻分不清谚咬,到底要注入那個(gè)鹦付,于是就會報(bào)Exception,這個(gè)時(shí)候我們可以使用@Qualifier具體指定以哪個(gè)實(shí)體類注入择卦。如果這樣的話敲长,當(dāng)我們在一個(gè)地方需要好多個(gè)解析器,我們得寫好多個(gè)@Autowired以及具體指定的@Qualifier秉继。
Spring的厲害之處祈噪,就是咱們的煩惱,他都能想得到尚辑,于是便有了將注入的Bean 放在List或者M(jìn)ap中這樣的 “玩法”辑鲤。
下面直接上例子:
我創(chuàng)建了一個(gè)接口叫做“Parent”然后有三個(gè)實(shí)現(xiàn)它的類分別為 “ChildA”,“ChildB”杠茬,“ChildC”月褥。然后創(chuàng)建了一個(gè)Controller類,用于注入那些Bean澈蝙。目錄結(jié)構(gòu)如下:
Parent 類代碼如下:
package com.example.injectdemo.model;
public interface Parent {
public void say();
}
Child類代碼如下:
package com.example.injectdemo.model;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component("ChildA")
public class ChildA implements Parent{
@Override
public void say() {
System.out.println("I am ChildA");
}
}
Tips:@Component一定要傳遞這個(gè)bean注入的名稱吓坚,因?yàn)樵谶@個(gè)時(shí)候spring不會自動幫我們把注入的bean的名稱處理好撵幽。
Controller類代碼如下:
package com.example.injectdemo;
import com.example.injectdemo.model.Parent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Controller
@RequestMapping("/test")
public class InjectController {
@Autowired
private Map<String, Parent> map;
@Autowired
private List<Parent> list;
@RequestMapping("/say")
public void sayTest(){
Set<Map.Entry<String, Parent>> sets = map.entrySet();
for(Map.Entry<String,Parent> item:sets){
System.out.println(item.getKey());
}
for(Parent parent : list){
parent.say();
}
}
}
Tips:Map的Key是實(shí)現(xiàn)類的名稱灯荧,Value為具體的類(Value的泛型為接口名稱)
啟動Application后,訪問URL盐杂,查看結(jié)果逗载,結(jié)果為:
ChildA
ChildB
ChildC
I am ChildA
I am childB
I am ChildC
Map我在這里不多說,通過代碼链烈,可以看的一清二楚厉斟。
List我在多說一點(diǎn):
如果我們不想讓調(diào)用的順序?yàn)镃hildA->ChildB->ChildC怎么辦。
我們可以分別在這三個(gè)實(shí)現(xiàn)的@Component注解下面加上@Order(number),這里的number 可以填寫數(shù)字强衡。數(shù)字越大擦秽,在list中越靠前。
加完之后 ChildA是這樣的:
package com.example.injectdemo.model;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component("ChildA")
@Order(3)
public class ChildA implements Parent{
@Override
public void say() {
System.out.println("I am ChildA");
}
}
其他的B,C分別加上 2和1
輸出的順序是:
ChildA
ChildB
ChildC
I am ChildC
I am childB
I am ChildA