Java面試題:讓依賴注入變得簡單,面對@Autowired和@Resource,該如何選擇?

猫鱼吐泡泡發表於2024-05-16

@Autowired和@Resource都是Java Spring框架中的註解,用於實現依賴注入(DI)和控制反轉(IoC)。

它們的區別主要在以下三個方面:


源頭不同

@Autowired是Spring自帶的註解,而@Resource是JSR 250規範中定義的註解。因此,在使用Spring框架的時候,通常建議使用@Autowired註解。

查詢順序不同

在注入Bean時,@Autowired註解的查詢順序為:先按型別(byType)匹配,如果有多個Bean符合該型別,則再按照名稱(byName)進行匹配。如果兩種方式都無法唯一確定Bean,則會丟擲異常。
虛擬碼如下:

public class Person {
    private Phone phone;

    @Autowired
    public void setPhone(Phone phone) {
        this.phone = phone;
    }

    //...
}

public interface Phone {
    //...
}

@Component("apple")
public class ApplePhone implements Phone {
    //...
}

@Component("huawei")
public class HuaweiPhone implements Phone {
    //...
}

在上面的示例中,如果有ApplePhone和HuaweiPhone兩個Bean都實現了Phone介面,那麼當Person類的setPhone方法被呼叫時,Spring會根據型別匹配到這兩個Bean,但是無法唯一確定,此時會丟擲異常。可以透過新增@Qualifier註解來指定具體的Bean:

虛擬碼如下:
@Autowired
@Qualifier("apple")
public void setPhone(Phone phone) {
    this.phone = phone;
}

而@Resource註解的查詢順序為:先按照名稱(byName)進行匹配,如果無法匹配到Bean,則再按照型別(byType)進行匹配。

虛擬碼如下:
public class Person {
    private Phone phone;

    @Resource(name = "apple")
    public void setPhone(Phone phone) {
        this.phone = phone;
    }

    //...
}

@Component("apple")
public class ApplePhone implements Phone {...}

@Component("huawei")
public class HuaweiPhone implements Phone {...}

在上面的示例中,當Person類的setPhone方法被呼叫時,Spring會先根據名稱查詢是否有名稱為"apple"的Bean,如果有,則直接注入;如果沒有,則再根據型別匹配。

適用範圍不同

@Autowired註解可以用於構造器、Setter方法、欄位和方法上,而@Resource註解只能用於欄位和方法上。因此,如果需要在構造器中注入Bean,就必須使用@Autowired註解。綜上所述,建議在使用Spring框架時,儘量使用@Autowired註解。
以下是具體的程式碼示例:

public interface Phone {
    String brand();
}

@Component("apple")
public class ApplePhone implements Phone {
    @Override
    public String brand() {
        return "Apple";
    }
}

@Component("huawei")
public class HuaweiPhone implements Phone {
    @Override
    public String brand() {
        return "Huawei";
    }
}

@Component
public class Person {

    // 使用@Autowired註解進行注入
    @Autowired
    private Phone phone1;

    // 使用@Resource註解進行注入,指定名稱
    @Resource(name = "apple")
    private Phone phone2;

    private Phone phone3;

    public void setPhone3(Phone phone3) {
        this.phone3 = phone3;
    }

    // 使用@Autowired註解和@Qualifier註解進行注入
    @Autowired
    @Qualifier("huawei")
    public void setPhone4(Phone phone4) {
        this.phone4 = phone4;
    }
}

在上面的示例中,Person類中有四個屬性需要注入Bean。其中,phone1屬性使用了@Autowired註解,使用預設的查詢方式進行注入;phone2屬性使用了@Resource註解,並指定了名稱為"apple"的Bean進行注入;phone3屬性沒有。

總結一下:

  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。

  • @Autowired預設按照型別自動裝配,而@Resource預設按照名稱自動裝配。

  • @Autowired支援@Qualifier註解來指定裝配哪一個具有相同型別的bean,而@Resource 預設按照名稱進行注入,如果指定了name或者type屬性,則會按照指定的名稱或者型別來查詢對應的Bean例項進行注入


綜上所述,@Autowired更加靈活,但也更加複雜;@Resource更加簡單、直觀,適用於簡單的場景。

往期面試題:

Java面試題:如果你這樣做,你會後悔的,兩次啟動同一個執行緒~~~

Java面試題:@PostConstruct、init-method和afterPropertiesSet執行順序?

Java面試題:SimpleDateFormat是執行緒安全的嗎?使用時應該注意什麼?

Java面試題:細數ThreadLocal大坑,記憶體洩露本可避免

Java面試題:請談談對ThreadLocal的理解?

Java面試題:為什麼HashMap不建議使用物件作為Key?

Java面試題:你知道Spring的IOC嗎?那麼,它為什麼這麼重要呢?

Java面試題:執行緒池內“鬧情緒”的執行緒,怎麼辦?

Java面試題:Spring Bean執行緒安全?別擔心,只要你不寫併發程式碼就好了!

Java面試題:Spring框架除了IOC和AOP,還有哪些好玩的設計模式?

相關文章