1. 概述
在本 Spring Framework 教程中,我們將演示如何使用與依賴注入相關的註解,包括 <em @Resource</em>、<em @Inject</em> 和 <em @Autowired</em> 註解。這些註解為類提供了聲明式解決依賴的方式。
@Autowired
ArbitraryClass arbObject;與直接實例化它們(命令式方式)相對,
ArbitraryClass arbObject = new ArbitraryClass();這三個註解中有兩個屬於 Java 擴展包:javax.annotation.Resource 和 javax.inject.Inject。 @Autowired 註解則屬於 org.springframework.beans.factory.annotation 包。
這些註解都可以通過字段注入或設置器注入來解決依賴關係。 我們將使用一個簡化的,但實用的例子來演示這三個註解的執行路徑之間的區別。
這些示例將側重於在集成測試中使用這三個注入註解的方式。 測試所需的依賴可以是任意文件或任意類。
2. <em itemprop="resource">@Resource</em> 註解
<em itemprop="resource">@Resource</em> 註解是 <a href="https://jcp.org/en/jsr/detail?id=250">JSR-250</a> 註解集合的一部分,並隨 Jakarta EE 一起打包。該註解具有以下執行路徑,按優先級排列:
- 按名稱匹配
- 按類型匹配
- 按指定者匹配
這些執行路徑適用於設置者和字段注入。
2.1. 字段注入 (Field Injection)
我們可以通過字段注入來解決依賴關係,通過對實例變量進行標註,使用 @Resource 註解。
2.1.1. 通過名稱匹配
我們將使用以下集成測試來演示通過名稱匹配的字段注入:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceNameType.class)
public class FieldResourceInjectionIntegrationTest {
@Resource(name="namedFile")
private File defaultFile;
@Test
public void givenResourceAnnotation_WhenOnField_ThenDependencyValid(){
assertNotNull(defaultFile);
assertEquals("namedFile.txt", defaultFile.getName());
}
}讓我們來分析一下代碼。在 FieldResourceInjectionTest 集成測試中,在第 7 行,我們通過將 Bean 名稱作為屬性值傳遞到 @Resource 註解中,來按名稱解決依賴關係:
@Resource(name="namedFile")
private File defaultFile;此配置將使用匹配名稱執行路徑來解決依賴項。必須在 ApplicationContextTestResourceNameType 應用程序上下文中定義名為 namedFile 的 Bean。
請注意,Bean ID 和相應的引用屬性值必須匹配。
@Configuration
public class ApplicationContextTestResourceNameType {
@Bean(name="namedFile")
public File namedFile() {
File namedFile = new File("namedFile.txt");
return namedFile;
}
}如果我們在應用程序上下文中未定義 Bean,則會拋出 org.springframework.beans.factory.NoSuchBeanDefinitionException 異常。我們可以通過修改 @Bean 註解中傳遞的屬性值,或者在 FieldResourceInjectionTest 集成測試中修改 @Resource 註解中傳遞的屬性值來演示這一點。
2.1.2. 匹配類型
為了演示匹配類型執行路徑,我們只需在 FieldResourceInjectionTest 集成測試的第 7 行刪除屬性值即可:
@Resource
private File defaultFile;然後我們再次運行測試。
測試仍然會通過,因為如果 @Resource 註解沒有接收到屬性值作為 bean 名稱,Spring 框架將使用下一個優先級級別,即按類型匹配,以嘗試解決依賴關係。
2.1.3. 按 Qualifier 匹配
為了演示按 Qualifier 執行路徑,集成測試場景將被修改,以便在 ApplicationContextTestResourceQualifier 應用程序上下文中定義兩個 bean:
@Configuration
public class ApplicationContextTestResourceQualifier {
@Bean(name="defaultFile")
public File defaultFile() {
File defaultFile = new File("defaultFile.txt");
return defaultFile;
}
@Bean(name="namedFile")
public File namedFile() {
File namedFile = new File("namedFile.txt");
return namedFile;
}
}我們將會使用 QualifierResourceInjectionTest 集成測試來演示基於限定符的依賴解析。 在此場景中,一個特定的 Bean 依賴需要注入到每個引用變量中:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceQualifier.class)
public class QualifierResourceInjectionIntegrationTest {
@Resource
private File dependency1;
@Resource
private File dependency2;
@Test
public void givenResourceAnnotation_WhenField_ThenDependency1Valid(){
assertNotNull(dependency1);
assertEquals("defaultFile.txt", dependency1.getName());
}
@Test
public void givenResourceQualifier_WhenField_ThenDependency2Valid(){
assertNotNull(dependency2);
assertEquals("namedFile.txt", dependency2.getName());
}
}當我們運行集成測試時,將會拋出 org.springframework.beans.factory.NoUniqueBeanDefinitionException 異常。這是因為應用程序上下文會找到兩個類型為 File 的 Bean 定義,並且無法確定哪個 Bean 應該用於解決依賴關係。
為了解決這個問題,我們需要參考 QualifierResourceInjectionTest 集成測試的第 7 到第 10 行:
@Resource
private File dependency1;
@Resource
private File dependency2;我們必須添加以下代碼行:
@Qualifier("defaultFile")
@Qualifier("namedFile")為了使代碼塊呈現如下所示:
@Resource
@Qualifier("defaultFile")
private File dependency1;
@Resource
@Qualifier("namedFile")
private File dependency2;當我們再次運行集成測試時,它應該通過。我們的測試表明,即使在應用程序上下文中定義了多個 Bean,我們也可以使用 @Qualifier 註解來消除歧義,從而允許我們向類注入特定的依賴項。
2.2. setter 注入
當依賴項注入到字段中時,所採用的執行路徑也適用於 setter 注入。
2.2.1. 通過名稱匹配
唯一不同之處在於 <em>MethodResourceInjectionTest</em> 集成測試包含一個 setter 方法:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceNameType.class)
public class MethodResourceInjectionIntegrationTest {
private File defaultFile;
@Resource(name="namedFile")
protected void setDefaultFile(File defaultFile) {
this.defaultFile = defaultFile;
}
@Test
public void givenResourceAnnotation_WhenSetter_ThenDependencyValid(){
assertNotNull(defaultFile);
assertEquals("namedFile.txt", defaultFile.getName());
}
}我們通過註解對應 setter 方法來解決依賴關係,從而實現 setter 注入。然後,我們將 bean 依賴的名稱作為屬性值傳遞給 @Resource</em/> 註解:
private File defaultFile;
@Resource(name="namedFile")
protected void setDefaultFile(File defaultFile) {
this.defaultFile = defaultFile;
}我們將在此示例中重用 namedFile Bean 依賴。 Bean 名稱和對應的屬性值必須匹配。
當運行集成測試時,它將通過。
為了驗證名稱匹配執行路徑是否解決了依賴關係,我們需要將 @Resource 註解中傳遞的屬性值更改為我們選擇的值,然後再次運行測試。 此時,測試將由於 NoSuchBeanDefinitionException 而失敗。
2.2.2 名稱匹配
為了演示基於 setter 的名稱匹配執行,我們將使用 MethodByTypeResourceTest 集成測試:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceNameType.class)
public class MethodByTypeResourceIntegrationTest {
private File defaultFile;
@Resource
protected void setDefaultFile(File defaultFile) {
this.defaultFile = defaultFile;
}
@Test
public void givenResourceAnnotation_WhenSetter_ThenValidDependency(){
assertNotNull(defaultFile);
assertEquals("namedFile.txt", defaultFile.getName());
}
}當我們運行此測試時,它將通過。
為了驗證 match-by-type 執行路徑是否解決了 File 依賴項,我們需要更改 defaultFile 變量的類類型為另一個類類型,例如 String。然後我們可以重新執行 MethodByTypeResourceTest 集成測試,此時將會拋出 NoSuchBeanDefinitionException。
此異常驗證了 match-by-type 確實被用於解決 File 依賴項。 NoSuchBeanDefinitionException 確認引用變量名稱與 bean 名稱不必匹配。 相反,依賴項解決取決於 bean 的類類型與引用變量的類類型匹配。
2.2.3. Match by Qualifier
我們將使用 MethodByQualifierResourceTest 集成測試來演示 match-by-qualifier 執行路徑:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceQualifier.class)
public class MethodByQualifierResourceIntegrationTest {
private File arbDependency;
private File anotherArbDependency;
@Test
public void givenResourceQualifier_WhenSetter_ThenValidDependencies(){
assertNotNull(arbDependency);
assertEquals("namedFile.txt", arbDependency.getName());
assertNotNull(anotherArbDependency);
assertEquals("defaultFile.txt", anotherArbDependency.getName());
}
@Resource
@Qualifier("namedFile")
public void setArbDependency(File arbDependency) {
this.arbDependency = arbDependency;
}
@Resource
@Qualifier("defaultFile")
public void setAnotherArbDependency(File anotherArbDependency) {
this.anotherArbDependency = anotherArbDependency;
}
}我們的測試表明,即使在應用程序上下文中定義了多種同類型的 Bean 實現,我們也可以使用 @Qualifier 註解與 @Resource 註解結合,來解決依賴關係。
類似於基於字段的依賴注入,如果在應用程序上下文中定義了多個 Bean,則必須使用 @Qualifier 註解來指定用於解決依賴關係的 Bean,否則將會拋出 NoUniqueBeanDefinitionException 異常。
3. 註解
註解 屬於 JSR-330 註解集合。該註解具有以下執行路徑,按優先級排列:- 按類型匹配
- 按指定者匹配
- 按名稱匹配
這些執行路徑適用於設置者和字段注入。為了訪問 註解,我們必須聲明 庫為 Gradle 或 Maven 依賴。
對於 Gradle:
testCompile group: 'javax.inject', name: 'javax.inject', version: '1'對於 Maven:
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>3.1. 字段注入
3.1.1. 按類型匹配
我們將修改集成測試示例,使用另一種類型的依賴項,即 <em class="ArbitraryDependency"></em> 類。 <em class="ArbitraryDependency"></em> 類依賴項僅作為一種簡單的依賴項存在,不具有任何進一步的意義。
@Component
public class ArbitraryDependency {
private final String label = "Arbitrary Dependency";
public String toString() {
return label;
}
}以下是 FieldInjectTest 集成測試:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestInjectType.class)
public class FieldInjectIntegrationTest {
@Inject
private ArbitraryDependency fieldInjectDependency;
@Test
public void givenInjectAnnotation_WhenOnField_ThenValidDependency(){
assertNotNull(fieldInjectDependency);
assertEquals("Arbitrary Dependency",
fieldInjectDependency.toString());
}
}與 @Resource 註解不同,其默認行為是首先通過名稱來解析依賴項。而 @Inject 註解的默認行為是按類型來解析依賴項。
這意味着,即使類引用變量名稱與 Bean 名稱不同,只要 Bean 被定義在應用程序上下文中,依賴項仍然會被解析。請注意以下測試中的引用變量名稱:
@Inject
private ArbitraryDependency fieldInjectDependency;與應用程序上下文配置的 Bean 名稱不同:
@Bean
public ArbitraryDependency injectDependency() {
ArbitraryDependency injectDependency = new ArbitraryDependency();
return injectDependency;
}當我們執行測試時,我們能夠解決依賴關係。
3.1.2. 通過限定符匹配
如果存在同一類別的多個實現,並且某個類需要特定的 Bean,該怎麼辦?讓我們修改集成測試示例,使其需要另一個依賴項。
在這個示例中,我們子類化了 ArbitraryDependency 類,該類在通過類型匹配示例中使用,以創建 AnotherArbitraryDependency 類:
public class AnotherArbitraryDependency extends ArbitraryDependency {
private final String label = "Another Arbitrary Dependency";
public String toString() {
return label;
}
}每個測試用例的目標是確保我們正確地將每個依賴項注入到每個引用變量中:
@Inject
private ArbitraryDependency defaultDependency;
@Inject
private ArbitraryDependency namedDependency;我們可以使用 FieldQualifierInjectTest 集成測試來演示通過限定符匹配:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestInjectQualifier.class)
public class FieldQualifierInjectIntegrationTest {
@Inject
private ArbitraryDependency defaultDependency;
@Inject
private ArbitraryDependency namedDependency;
@Test
public void givenInjectQualifier_WhenOnField_ThenDefaultFileValid(){
assertNotNull(defaultDependency);
assertEquals("Arbitrary Dependency",
defaultDependency.toString());
}
@Test
public void givenInjectQualifier_WhenOnField_ThenNamedFileValid(){
assertNotNull(defaultDependency);
assertEquals("Another Arbitrary Dependency",
namedDependency.toString());
}
}如果應用程序上下文中有同一類的多個實現,並且 FieldQualifierInjectTest 集成測試嘗試按照以下方式注入依賴項,則會拋出 NoUniqueBeanDefinitionException 異常:
@Inject
private ArbitraryDependency defaultDependency;
@Inject
private ArbitraryDependency namedDependency;拋出此異常是 Spring Framework 的一種方式,表明存在多個類實現的變體,並且它對應該使用哪個變體感到困惑。為了闡明這種困惑,我們可以查看 <em>FieldQualifierInjectTest</em> 集成測試的第 7 行和第 10 行:FieldQualifierInjectTest
@Inject
private ArbitraryDependency defaultDependency;
@Inject
private ArbitraryDependency namedDependency;我們可以將所需的 Bean 名稱傳遞給 @Qualifier 註解,該註解與 @Inject 註解一起使用。代碼塊現在將如下所示:
@Inject
@Qualifier("defaultFile")
private ArbitraryDependency defaultDependency;
@Inject
@Qualifier("namedFile")
private ArbitraryDependency namedDependency;@Qualifier 註解在接收 Bean 名稱時要求嚴格匹配。我們必須確保 Bean 名稱正確地傳遞給@Qualifier,否則將會拋出NoUniqueBeanDefinitionException 異常。如果再次運行測試,它應該通過。
3.1.3. 通過名稱匹配
FieldByNameInjectTest 集成測試用於演示通過名稱匹配,與通過類型執行路徑類似。唯一的區別在於,現在我們要求一個特定的 Bean,而不是一個特定的類型。在這個例子中,我們再次繼承ArbitraryDependency 類來生成YetAnotherArbitraryDependency 類:
public class YetAnotherArbitraryDependency extends ArbitraryDependency {
private final String label = "Yet Another Arbitrary Dependency";
public String toString() {
return label;
}
}為了演示匹配-按名稱的執行路徑,我們將使用以下集成測試:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestInjectName.class)
public class FieldByNameInjectIntegrationTest {
@Inject
@Named("yetAnotherFieldInjectDependency")
private ArbitraryDependency yetAnotherFieldInjectDependency;
@Test
public void givenInjectQualifier_WhenSetOnField_ThenDependencyValid(){
assertNotNull(yetAnotherFieldInjectDependency);
assertEquals("Yet Another Arbitrary Dependency",
yetAnotherFieldInjectDependency.toString());
}
}我們列出應用程序上下文:
@Configuration
public class ApplicationContextTestInjectName {
@Bean
public ArbitraryDependency yetAnotherFieldInjectDependency() {
ArbitraryDependency yetAnotherFieldInjectDependency =
new YetAnotherArbitraryDependency();
return yetAnotherFieldInjectDependency;
}
}如果運行集成測試,它將通過。
為了驗證我們通過匹配執行路徑注入了依賴項,我們需要更改傳遞給 @Named 註解的值,該值是 yetAnotherFieldInjectDependency。再次運行測試時,將會拋出 NoSuchBeanDefinitionException。
3.2. setter 注入
setter 注入基於 @Inject 註解的方式與基於 @Resource 的 setter 注入方式類似。 無需在引用變量上進行註解,而是對相應的 setter 方法進行註解。 與基於字段的依賴注入所遵循的執行路徑同樣適用於 setter 注入。
4. @Autowired 註解
@Autowired 註解的行為與@Inject 註解類似。唯一的區別在於@Autowired 註解是 Spring 框架的一部分。該註解的執行路徑與@Inject 註解相同,按優先級順序排列如下:
- 按類型匹配
- 按名稱/別名匹配
- 按名稱匹配
這些執行路徑適用於 setter 和 field 注入。
4.1. 字段注入
4.1.1. 通過類型匹配
用於演示 @Autowired 通過類型匹配執行路徑的集成測試示例將與用於演示 @Inject 通過類型匹配執行路徑的測試類似。我們使用以下 FieldAutowiredTest 集成測試來演示使用 @Autowired 註解的通過類型匹配:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestAutowiredType.class)
public class FieldAutowiredIntegrationTest {
@Autowired
private ArbitraryDependency fieldDependency;
@Test
public void givenAutowired_WhenSetOnField_ThenDependencyResolved() {
assertNotNull(fieldDependency);
assertEquals("Arbitrary Dependency", fieldDependency.toString());
}
}我們列出了本次集成測試的應用上下文:
@Configuration
public class ApplicationContextTestAutowiredType {
@Bean
public ArbitraryDependency autowiredFieldDependency() {
ArbitraryDependency autowiredFieldDependency =
new ArbitraryDependency();
return autowiredFieldDependency;
}
}我們使用此集成測試來證明匹配按類型優先於其他執行路徑。請注意,在 FieldAutowiredTest 集成測試的第 8 行上,引用變量的名稱:
@Autowired
private ArbitraryDependency fieldDependency;這是與應用程序上下文中的 bean 名稱不同。
@Bean
public ArbitraryDependency autowiredFieldDependency() {
ArbitraryDependency autowiredFieldDependency =
new ArbitraryDependency();
return autowiredFieldDependency;
}當我們運行測試時,它應該通過。
為了確認依賴項確實使用了匹配-按類型執行路徑進行解決,我們需要更改 fieldDependency 引用變量的類型並重新運行集成測試。 這一次,FieldAutowiredTest 集成測試將失敗,並拋出 NoSuchBeanDefinitionException。
4.1.2. 匹配器(Qualifier)
如果我們在應用程序上下文中定義了多個 Bean 實現,該怎麼辦?
@Configuration
public class ApplicationContextTestAutowiredQualifier {
@Bean
public ArbitraryDependency autowiredFieldDependency() {
ArbitraryDependency autowiredFieldDependency =
new ArbitraryDependency();
return autowiredFieldDependency;
}
@Bean
public ArbitraryDependency anotherAutowiredFieldDependency() {
ArbitraryDependency anotherAutowiredFieldDependency =
new AnotherArbitraryDependency();
return anotherAutowiredFieldDependency;
}
}如果執行以下 FieldQualifierAutowiredTest 集成測試,將會拋出 NoUniqueBeanDefinitionException 異常:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestAutowiredQualifier.class)
public class FieldQualifierAutowiredIntegrationTest {
@Autowired
private ArbitraryDependency fieldDependency1;
@Autowired
private ArbitraryDependency fieldDependency2;
@Test
public void givenAutowiredQualifier_WhenOnField_ThenDep1Valid(){
assertNotNull(fieldDependency1);
assertEquals("Arbitrary Dependency", fieldDependency1.toString());
}
@Test
public void givenAutowiredQualifier_WhenOnField_ThenDep2Valid(){
assertNotNull(fieldDependency2);
assertEquals("Another Arbitrary Dependency",
fieldDependency2.toString());
}
}由於應用程序上下文定義了兩個 Bean,因此產生了歧義。Spring 框架不知道哪個 Bean 依賴項應該自動注入到哪個引用變量中。我們可以通過向 FieldQualifierAutowiredTest 集成測試的第 7 行和第 10 行添加 @Qualifier 註解來解決此問題:
@Autowired
private FieldDependency fieldDependency1;
@Autowired
private FieldDependency fieldDependency2;為了使代碼塊呈現如下所示:
@Autowired
@Qualifier("autowiredFieldDependency")
private FieldDependency fieldDependency1;
@Autowired
@Qualifier("anotherAutowiredFieldDependency")
private FieldDependency fieldDependency2;當我們再次運行測試時,它將通過。
4.1.3. 通過名稱匹配
我們將使用相同的集成測試場景來演示使用 @Autowired 註解注入字段依賴項的通過名稱執行路徑。當通過名稱注入依賴項時,必須使用 @ComponentScan 註解與應用程序上下文一起使用,例如:ApplicationContextTestAutowiredName。
@Configuration
@ComponentScan(basePackages={"com.baeldung.dependency"})
public class ApplicationContextTestAutowiredName {
}我們使用 @ComponentScan 註解來搜索 Java 包中,帶有 @Component 註解標記的類。例如,在應用程序上下文中,com.baeldung.dependency 包將被掃描以查找帶有 @Component 註解標記的類。在這種情況下,Spring 框架必須檢測到 ArbitraryDependency 類,該類具有 @Component 註解。
@Component(value="autowiredFieldDependency")
public class ArbitraryDependency {
private final String label = "Arbitrary Dependency";
public String toString() {
return label;
}
}屬性值 autowiredFieldDependency,傳遞到 @Component 註解中,告訴 Spring 框架 ArbitraryDependency 類是一個名為 autowiredFieldDependency 的組件。為了使 @Autowired 註解通過名稱解析依賴項,組件名稱必須與 FieldAutowiredNameTest 集成測試中定義的字段名稱相對應;請參閲第 8 行:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestAutowiredName.class)
public class FieldAutowiredNameIntegrationTest {
@Autowired
private ArbitraryDependency autowiredFieldDependency;
@Test
public void givenAutowired_WhenSetOnField_ThenDependencyResolved(){
assertNotNull(autowiredFieldDependency);
assertEquals("Arbitrary Dependency",
autowiredFieldDependency.toString());
}
}當我們運行 FieldAutowiredNameTest 集成測試時,測試會通過。
但是,我們如何知道 @Autowired 註解是否確實觸發了基於名稱的執行路徑?我們可以將引用變量 autowiredFieldDependency 的名稱更改為我們選擇的另一個名稱,然後重新運行測試。
這次測試將會失敗,並拋出 NoUniqueBeanDefinitionException 異常。類似的檢查方法是更改 @Component 屬性值,autowiredFieldDependency,為另一個我們選擇的值,然後重新運行測試。 也會拋出 NoUniqueBeanDefinitionException 異常。
這個異常證明,如果使用錯誤的 bean 名稱,則不會找到有效的 bean。 這就是我們知道基於名稱的執行路徑被觸發的原因。
4.2. setter 注入
setter 注入基於 @Autowired 標註的機制與用於 @Resource 的 setter 注入方式類似。 相較於使用 @Inject 標註引用變量,我們標註相應的 setter 方法。 setter 注入所遵循的執行路徑也與基於字段的依賴注入所遵循的路徑相同。
5. 應用這些標註
這引發了關於應該使用哪種標註以及在什麼情況下使用的疑問。這些問題的答案取決於應用程序所面臨的設計場景,以及開發者希望如何利用基於每個標註的默認執行路徑的多態性。
5.1. 通過多態實現應用程序範圍內的單例使用
如果設計使得應用程序行為基於接口或抽象類的實現,並且這些行為在整個應用程序中被使用,那麼我們可以使用 @Inject 或 @Autowired 註解。
這種方法的優勢在於,在升級應用程序或應用補丁以修復錯誤時,可以最大限度地減少對整體應用程序行為的負面影響。在這種情況下,主要執行路徑是基於類型匹配。
5.2. 通過多態配置精細化應用行為
如果應用程序的設計使得每個行為都基於不同的接口/抽象類,並且每個實現的用法在應用程序中各不相同,那麼我們可以使用 <em/>@Resource</em/> 註解。在這種情況下,主要的默認執行路徑是按名稱匹配。
5.3. 依賴注入應完全由 Jakarta EE 平台處理
如果設計要求所有依賴項都由 Jakarta EE 平台注入,而不是 Spring,那麼選擇將落在 <em @Resource</em> 註解和 <em @Inject</em> 註解之間。我們應根據所需的默認執行路徑來縮小這兩個註解之間的最終選擇。
5.4. 依賴注入應完全由 Spring 框架處理
如果要求所有依賴項都由 Spring 框架處理,唯一的選擇是 <em @Autowired</em>> 註解。
5.5. 討論總結
下表總結了我們的討論內容。
| 場景 | @Resource | @Inject | @Autowired |
|---|---|---|---|
| 通過多態實現全局單例的使用 | ✗ | ✔ | ✔ |
| 通過多態配置精細的應用程序行為 | ✔ | ✗ | ✗ |
| 依賴注入應由 Jakarta EE 平台完全處理 | ✔ | ✔ | ✗ |
| 依賴注入應由 Spring Framework 框架完全處理 | ✗ | ✗ | ✔ |