作者:Richard_Yi
來源:juejin.cn/post/6844904056230690824
本章的內容主要是想探討我們在進行Spring 開發過程當中,關於依賴注入的幾個問題。感興趣的讀者可以先看下以下三點:
@Autowired
,@Resource
,@Inject
三個注解的區別- 當你在使用
@Autowired
時,是否有出現過Field injection is not recommended
的警告?你知道這是為什么嗎? - Spring 依賴注入有哪幾種方式?官方是怎么建議使用的呢?
如果你對上述問題都了解,那我個人覺得你的開發經驗應該是不錯的👍。如果你看到這三個問題很懵可以往下看。
下面我們就依次對上述問題進行解答,並且總結知識點。
@Autowired
, @Resource
, @Inject
三個注解的區別
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
來處理的。
@Inject
是 JSR-330 定義的規范,如果使用這種方式,切換到Guice
也是可以的。
Guice 是 google 開源的輕量級 DI 框架
如果硬要說兩個的區別,首先@Inject
是Java EE包里的,在SE環境需要單獨引入。另一個區別在於@Autowired
可以設置required=false
而@Inject
並沒有這個屬性。
@Resource
@Resource
是JSR-250定義的注解。Spring 在 CommonAnnotationBeanPostProcessor
實現了對JSR-250
的注解的處理,其中就包括@Resource
。
@Resource
有兩個重要的屬性:name
和type
,而Spring 將@Resource
注解的name
屬性解析為bean的名字,而type
屬性則解析為bean的類型。
裝配順序:
- 如果同時指定了
name
和type
,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常。 - 如果指定了
name
,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常。 - 如果指定了
type
,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或是找到多個,都會拋出異常。 - 如果既沒有指定
name
,又沒有指定type
,則默認按照byName
方式進行裝配;如果沒有匹配,按照byType
h進行裝配。
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2021最新版)
2.別在再滿屏的 if/ else 了,試試策略模式,真香!!
3.卧槽!Java 中的 xx ≠ null 是什么新語法?
4.Spring Boot 2.5 重磅發布,黑暗模式太炸了!
覺得不錯,別忘了隨手點贊+轉發哦!