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

@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,還有哪些好玩的設計模式?

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章