天天看點

@Autowired, @Resource, @Inject 三個注解的差別你懂嗎?别再亂用了!

本章的内容主要是想探讨我們在進行Spring 開發過程當中,關于依賴注入的幾個問題。感興趣的讀者可以先看下以下三點:

@Autowired, @Resource, @Inject 三個注解的差別

當你在使用@Autowired時,是否有出現過Field injection is not recommended的警告?你知道這是為什麼嗎?

Spring 依賴注入有哪幾種方式?官方是怎麼建議使用的呢?

如果你對上述問題都了解,那我個人覺得你的開發經驗應該是不錯的👍。如果你看到這三個問題很懵可以往下看。

下面我們就依次對上述問題進行解答,并且總結知識點。

Spring 支援使用@Autowired, @Resource, @Inject 三個注解進行依賴注入。下面來介紹一下這三個注解有什麼差別。

推薦一個 Spring Boot 基礎教程及實戰示例:

https://github.com/javastacks/javastack

@Autowired

@Autowired為Spring 架構提供的注解,需要導入包org.springframework.beans.factory.annotation.Autowired。

這裡先給出一個示例代碼,友善講解說明:

public interface Svc {

    void sayHello();
}

@Service
public class SvcA implements Svc {

    @Override
    public void sayHello() {
        System.out.println("hello, this is service A");
    }

}

@Service
public class SvcB implements Svc {

    @Override
    public void sayHello() {
        System.out.println("hello, this is service B");
    }

}

@Service
public class SvcC implements Svc {

    @Override
    public void sayHello() {
        System.out.println("hello, this is service C");
    }
}      

測試類:

@SpringBootTest
public class SimpleTest {

    @Autowired
    // @Qualifier("svcA")
    Svc svc;

    @Test
    void rc() {
        Assertions.assertNotNull(svc);
        svc.sayHello();
    }

}      

裝配順序:

1.按照type在上下文中查找比對的bean,查找type為Svc的bean

2.如果有多個bean,則按照name進行比對

如果有@Qualifier注解,則按照@Qualifier指定的name進行比對,查找name為svcA的bean

如果沒有,則按照變量名進行比對,查找name為svcA的bean

3.比對不到,則報錯。(@Autowired(required=false),如果設定required為false(預設為true),則注入失敗時不會抛出異常)

@Inject

在Spring 的環境下,@Inject和@Autowired 是相同的,因為它們的依賴注入都是使用AutowiredAnnotationBeanPostProcessor來處理的。

@Autowired, @Resource, @Inject 三個注解的差別你懂嗎?别再亂用了!

@Inject是 JSR-330 定義的規範,如果使用這種方式,切換到Guice也是可以的。

Guice 是 google 開源的輕量級 DI 架構

如果硬要說兩個的差別,首先@Inject是Java EE包裡的,在SE環境需要單獨引入。另一個差別在于@Autowired可以設定required=false而@Inject并沒有這個屬性。

@Resource

@Resource是JSR-250定義的注解。Spring 在 CommonAnnotationBeanPostProcessor實作了對JSR-250的注解的處理,其中就包括@Resource。

@Autowired, @Resource, @Inject 三個注解的差別你懂嗎?别再亂用了!

@Resource有兩個重要的屬性:name和type,而Spring 将@Resource注解的name屬性解析為bean的名字,而type屬性則解析為bean的類型。

如果同時指定了name和type,則從Spring上下文中找到唯一比對的bean進行裝配,找不到則抛出異常。

如果指定了name,則從上下文中查找名稱(id)比對的bean進行裝配,找不到則抛出異常。

如果指定了type,則從上下文中找到類型比對的唯一bean進行裝配,找不到或是找到多個,都會抛出異常。

如果既沒有指定name,又沒有指定type,則預設按照byName方式進行裝配;如果沒有比對,按照byTypeh進行裝配。