跳转至

@Autowired, @Qualifier

@Autowired

通常是加在class變數上

根據變數的類型 ,去 Spring 容器中尋找有沒有符合類型的 bean

public class Teacher{
    // step3 :printer 變數的類型盡量使用"interface" ,在這邊是用 Printer 
    // 因為@Autowired 是根據變數的類型去Spring 容器中尋找有沒有符合類型的bean
    @Autowired
    private Printer printer; // step2: 所以類型符合 ,依賴注入成功
    public void teach(){
            printer.print("I'm a teacher!");
    }
}

Printer hpPrinter = new HpPrinter(); // step1: hpPrinter可以向上轉型成Printer 

目的: 讓其關聯性降低

通常步驟:

  1. 創建一個 interface
  2. 接著寫一個 class 去實現這個 interface
  3. 如果要改換 class ,完全不需要修改 Teacher 的內容

如果同時有兩個class 同時去實現了Printer ,那@Autowired 它到底是要講哪一個bean交給 Teacher???

@Qualifier

通常是加在 class 變數上 ,會跟 @Autowired 一起用

指定要載入的bean名字

public class Teacher{
    @Autowired
    @Qualifier("hpPrinter") // 指定要載入的bean的名字
    private Printer printer; 
    public void teach(){
            printer.print("I'm a teacher!");
    }
}

// Bean hpPrinter 
@Component
public class HpPrinter implements Printer{

}

// Bean canonPrinter 
@Component
public class CanonPrinter implements Printer{

}
  • 當 Spring 創建 bean 的時候 ,bean 的名字會是 classname 第一個字母會轉成小寫

註解沒有順序性

public class Teacher{
    @Autowired
    @Qualifier("hpPrinter")
    private Printer printer; 
    public void teach(){
            printer.print("I'm a teacher!");
    }
}

// 或是寫這樣也可以
public class Teacher{
    @Qualifier("hpPrinter")
    @Autowired
    private Printer printer; 
    public void teach(){
            printer.print("I'm a teacher!");
    }
}

練習

建立一個Printer介面

兩個不同的印表機去實作這個 interface

接著切回 main 方法執行

在網址上輸入 localhost:8080/test (因為@RequestMapping("/test"))

因為我們加上 @Qualifier 指定要注入的 bean 是”canonPrinter “

所以 console 打印的是 canon 的印表機

console:

Canon印表機: Hello

如果沒有加上 @Qualifier 指定是哪個 bean 的話

***************************
APPLICATION FAILED TO START
***************************
Description:

Field printer in com.example.demo.MyController required a single bean, but 2 were found:
- canonPrinter: defined in file [D:\springboot\Work_Java_eclipse\spring0123\target\classes\com\example\demo\CanonPrinter.class]
- hpPrinter: defined in file [D:\springboot\Work_Java_eclipse\spring0123\target\classes\com\example\demo\HpPrinter.class]

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

錯誤訊息: 因為沒有指定要載入的是哪個bean ,所以無法運行