春の配線:@Autowired、@Resource、および@Inject
1概要
このSpring Frameworkの記事では、依存性注入に関連するアノテーション、つまり
@ Resource
、
@ Inject
、および
@ Autowired
アノテーションの使用方法について説明します。これらのアノテーションは、依存関係を解決するための宣言的な方法をクラスに提供します。例えば:
@Autowired
ArbitraryClass arbObject;
それらを直接インスタンス化するのではなく(命令型の方法)、例えば:
ArbitraryClass arbObject = new ArbitraryClass();
3つの注釈のうち2つはJava拡張パッケージに属します。
javax.annotation.Resource
および
javax.inject.Inject
。
@ Autowired
アノテーションは
org.springframework.beans.factory.annotation
パッケージに属しています。
これらの各注釈は、フィールドインジェクションまたはセッターインジェクションによって依存関係を解決できます。各アノテーションの実行パスに基づいて、3つのアノテーション間の違いを示すために、単純化された実用的な例を使用します。
例では、統合テスト中に3つの注入アノテーションを使用する方法に焦点を当てます。テストに必要な依存関係は、任意のファイルまたは任意のクラスです。
2
@リソース
注釈
@ Resource
アノテーションはhttps://jcp.org/en/jsr/detail?id=250[JSR-250]アノテーションコレクションの一部であり、Java EEと共にパッケージされています。この注釈には、優先順位の高い以下の実行パスがあります。
-
名前で一致
-
タイプで一致
-
修飾子による一致
これらの実行パスは、セッター注入とフィールド注入の両方に適用できます。
2.1. フィールドインジェクション
フィールドインジェクションによる依存関係の解決は、
@ Resource
アノテーションを使用してインスタンス変数にアノテーションを付けることによって実現されます。
* 2.1.1。名前で一致**
名前によるフィールドインジェクションを実証するために使用された統合テストは次のとおりです。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceNameType.class)
public class FieldResourceInjectionTest {
@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;
この設定は、名前による実行パスを使用して依存関係を解決します。 Bean
namedFile
は、
ApplicationContextTestResourceNameType
アプリケーションコンテキストで定義する必要があります。
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
がスローされます。これは、
ApplicationContextTestResourceNameType
アプリケーションコンテキストで、@ @ Bean
アノテーションに渡された属性値を変更することによって実証できます。または、
FieldResourceInjectionTest
統合テストで、
@ Resource__アノテーションに渡された属性値を変更する。
2.1.2. タイプで一致
型による実行パスを示すには、
FieldResourceInjectionTest
統合テストの7行目の属性値を削除して、次のようになるようにします。
@Resource
private File defaultFile;
そしてテストを再度実行してください。
@ Resource
アノテーションがBeanの名前を属性値として受け取らない場合、Spring Frameworkは依存性を解決するために次のレベルの優先順位match-by-typeを続行するため、テストは成功します。
2.1.3. 限定子によるマッチング
修飾子による実行パスを示すために、
ApplicationContextTestResourceQualifier
アプリケーションコンテキストに2つの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
統合テストは、match-by-qualifier依存関係の解決を実証するために使用されます。このシナリオでは、特定のBean依存関係を各参照変数に挿入する必要があります。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceQualifier.class)
public class QualifierResourceInjectionTest {
@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定義を2つ見つけたため、どの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. セッター注入
フィールドへの依存関係を注入するときに実行される実行パスは、セッターベースの注入に適用できます。
2.2.1. 名前で一致
唯一の違いは、
MethodResourceInjectionTest
統合テストにセッターメソッドがあることです。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceNameType.class)
public class MethodResourceInjectionTest {
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());
}
}
セッターインジェクションによる依存関係の解決は、参照変数の対応するセッターメソッドに注釈を付けることによって行われます。 Beanの依存関係の名前を属性値として
@ Resource
アノテーションに渡します。
private File defaultFile;
@Resource(name="namedFile")
protected void setDefaultFile(File defaultFile) {
this.defaultFile = defaultFile;
}
この例では、
namedFile
Beanの依存関係が再利用されます。 Bean名と対応する属性値は一致しなければなりません。
そのまま統合テストを実行すると合格です。
依存関係が実際に名前による一致実行パスによって解決されたことを確認するには、
@ Resource
アノテーションに渡された属性値を任意の値に変更して、テストを再実行してください。今回は、テストは
NoSuchBeanDefinitionException
で失敗します。
2.2.2. タイプで一致
セッターベースの型による実行の実行を実証するために、
MethodByTypeResourceTest
統合テストを使用します。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceNameType.class)
public class MethodByTypeResourceTest {
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());
}
}
このテストをそのまま実行すると、成功します。
File
依存関係が型による実行パスによって実際に解決されたことを確認するには、
defaultFile
変数のクラス型を
String
などの別のクラス型に変更します。
MethodByTypeResourceTest
統合テストを再度実行すると、今度は
NoSuchBeanDefinitionException
がスローされます。
この例外は、
File
依存関係を解決するために型による一致が実際に使用されたことを検証します。
NoSuchBeanDefinitionException
は、参照変数名がBean名と一致する必要がないことを確認します。代わりに、依存関係の解決は、参照変数のクラス型と一致するBeanのクラス型に依存します。
2.2.3. 限定子によるマッチング
MethodByQualifierResourceTest
統合テストは、match-by-qualifier実行パスを示すために使用されます。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestResourceQualifier.class)
public class MethodByQualifierResourceTest {
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が定義されている場合、依存関係の解決に使用するBeanを指定するために
@ Qualifier
アノテーションを使用しないと
NoUniqueBeanDefinitionException
がスローされます。
3
@ Inject
アノテーション
@ Inject
アノテーションはhttps://jcp.org/en/jsr/detail?id=330[JSR-330]アノテーションコレクションに属します。
この注釈には、優先順位の高い以下の実行パスがあります。
-
タイプで一致
-
修飾子による一致
-
名前で一致
これらの実行パスは、セッター注入とフィールド注入の両方に適用できます。
@ Inject
アノテーションにアクセスするには、
javax.inject
ライブラリを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. タイプで一致
統合テストの例は、別の種類の依存関係、つまり
ArbitraryDependency
クラスを使用するように変更されます。
ArbitraryDependency
クラスの依存関係は、単純な依存関係としてのみ機能し、それ以上の意味はありません。それは次のようにリストされています。
@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 FieldInjectTest {
@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が必要な場合はどうなりますか?別の依存関係が必要になるように統合テストの例を変更しましょう。
この例では、
AnotherArbitraryDependency
クラスを作成するために、match-by-typeの例で使用された
ArbitraryDependency
クラスをサブクラス化します。
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 FieldQualifierInjectTest {
@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
統合テストが以下にリストされた方法で依存関係を注入しようとした場合
@Inject
private ArbitraryDependency defaultDependency;
@Inject
private ArbitraryDependency namedDependency;
NoUniqueBeanDefinitionException
がスローされます。
この例外を投げるのは、Spring Frameworkが特定のクラスに複数の実装があり、どちらを使用するかについて混乱していることを指摘する方法です。混乱を解明するために、
FieldQualifierInjectTest
統合テストの7行目と10行目に進みます。
@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 FieldByNameInjectTest {
@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. セッター注入
@ Inject
アノテーションのセッターベースのインジェクションは、
@ Resource
セッターベースのインジェクションに使用されるアプローチと似ています。参照変数に注釈を付ける代わりに、対応する設定メソッドに注釈を付けます。フィールドベースの依存性注入が後に続く実行パスは、セッターベースの注入にも適用されます。
4
@ Autowired
アノテーション
@ Autowired
アノテーションの動作は
@ Inject
アノテーションと似ています。唯一の違いは、
@ Autowired
アノテーションがSpringフレームワークの一部であるということです。このアノテーションは
@ Inject
アノテーションと同じ実行パスを持ち、優先順位の高い順にリストされています。
-
タイプで一致
-
修飾子による一致
-
名前で一致
これらの実行パスは、セッター注入とフィールド注入の両方に適用できます。
4.1. フィールドインジェクション
4.1.1. タイプで一致
@ Autowired
match-by-type実行パスのデモに使用された統合テストの例は、
@ Inject
type-by-type実行パスのデモに使用されたテストと似ています。
@ Autowired
アノテーションを使用して型による一致を実証するために使用された
FieldAutowiredTest
統合テストは次のとおりです。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestAutowiredType.class)
public class FieldAutowiredTest {
@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
参照変数のタイプを変更して、統合テストを再度実行してください。今回は、
FoSAutowiredTest
統合テストが失敗し、
NoSuchBeanDefinitionException
がスローされます。これは、タイプによる突き合わせが依存関係を解決するために使用されたことを検証します。
4.1.2. 限定子によるマッチング
下記のように、アプリケーションのコンテキストで複数の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
統合テストが実行されると、
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestAutowiredQualifier.class)
public class FieldQualifierAutowiredTest {
@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());
}
}
NoUniqueBeanDefinitionException
がスローされます。
例外は、アプリケーションコンテキストで定義されている2つのBeanによるあいまいさのためです。 Spring Frameworkは、どの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
アノテーションは、
@ Component
アノテーションが付けられたJavaクラスのパッケージを検索します。たとえば、アプリケーションのコンテキストでは、
@ Component
アノテーションでアノテーションが付けられているクラスについて
com.baeldung.dependency
パッケージがスキャンされます。このシナリオでは、Spring Frameworkは
@ Component
アノテーションを持つ
ArbitraryDependency
クラスを検出する必要があります。
@Component(value="autowiredFieldDependency")
public class ArbitraryDependency {
private final String label = "Arbitrary Dependency";
public String toString() {
return label;
}
}
@ Component
アノテーションに渡された属性値
autowiredFieldDependency
は、
ArbitraryDependency
クラスが
autowiredFieldDependency
という名前のコンポーネントであることをSpring Frameworkに伝えます。
@ Autowired
アノテーションが名前によって依存関係を解決するには、コンポーネント名が
FieldAutowiredNameTest
統合テストで定義されたフィールド名と一致している必要があります。 8行目を参照してください。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
loader=AnnotationConfigContextLoader.class,
classes=ApplicationContextTestAutowiredName.class)
public class FieldAutowiredNameTest {
@Autowired
private ArbitraryDependency autowiredFieldDependency;
@Test
public void givenAutowiredAnnotation__WhenOnField__ThenDepValid(){
assertNotNull(autowiredFieldDependency);
assertEquals("Arbitrary Dependency",
autowiredFieldDependency.toString());
}
}
FieldAutowiredNameTest
統合テストをそのまま実行すると、成功します。
しかし、
@ Autowired
アノテーションが実際にmatch-by-name実行パスを呼び出したことをどうやって知ることができるでしょうか。参照変数
autowiredFieldDependency
の名前を任意の別の名前に変更してから、テストを再実行してください。
今回はテストは失敗し、
NoUniqueBeanDefinitionException
がスローされます。同様の確認として、
@ Component
属性値
autowiredFieldDependency
を、選択した別の値に変更して、テストを再実行してください。
NoUniqueBeanDefinitionException
もスローされます。
この例外は、誤ったBean名が使用された場合、有効なBeanが見つからないことを証明しています。したがって、名前による実行パスが呼び出されました。
4.2. セッター注入
@ Autowired
アノテーションのセッターベースのインジェクションは、
@ Resource
セッターベースのインジェクションで示したアプローチと似ています。
@ Inject
アノテーションで参照変数にアノテーションを付ける代わりに、対応するセッターにアノテーションを付けます。実行パスとそれに続くフィールドベースの依存関係注入は、セッターベースの注入にも適用されます。
5これらの注釈を適用する
これは、どの注釈がどのような状況下で使用されるべきかという疑問を提起します。これらの質問に対する答えは、問題のアプリケーションが直面している設計シナリオと、各アノテーションのデフォルトの実行パスに基づいて開発者がポリモーフィズムをどのように活用したいかによって異なります。
5.1. 多型によるシングルトンのアプリケーション全体での使用
アプリケーションの動作がインタフェースまたは抽象クラスの実装に基づいており、これらの動作がアプリケーション全体で使用されるように設計されている場合は、
@ Inject
または
@ Autowired
注釈を使用します。
このアプローチの利点は、アプリケーションがアップグレードされたとき、またはバグを修正するためにパッチを適用する必要があることです。そうすれば、アプリケーション全体の動作への悪影響を最小限に抑えながらクラスを交換できます。このシナリオでは、主要なデフォルトの実行パスはタイプによる一致です。
5.2. ポリモーフィズムによるきめ細かいアプリケーション動作設定
アプリケーションが複雑な振る舞いをするように設計されていて、それぞれの振る舞いが異なるインターフェース/抽象クラスに基づいており、これらの各実装の使用法がアプリケーションによって異なる場合は、
@ Resource
アノテーションを使用します。このシナリオでは、デフォルトの主な実行パスは名前による一致です。
5.3. 依存性注入はJava EEプラットフォームによってのみ処理されるべきです
Springではなく、すべての依存関係をJava EEプラットフォームによってインジェクトするという設計上の指示がある場合、選択は
@ Resource
アノテーションと
@ Inject
アノテーションのどちらかです。どちらのデフォルト実行パスが必要かに基づいて、2つのアノテーション間の最終決定を絞り込む必要があります。
** 5.4. 依存性注入はSpring Frameworkによってのみ処理されるべきです
すべての依存関係がSpring Frameworkによって処理されることがマンデートである場合、唯一の選択は
@ Autowired
アノテーションです。
5.5. ディスカッションサマリー
以下の表はその説明をまとめたものです。
| =================================================== ===================== |シナリオ| @Resource | @Inject | @Autowired |多態性によるシングルトンのアプリケーション全体での使用|✗|✔|✔
|多態性によるきめ細かいアプリケーション動作設定|✔|✗|✗
|依存性注入は、Java EEプラットフォームによってのみ処理されるべきです|✔|✔|✗
|依存性注入はSpring Frameworkによってのみ処理されるべきです|✗|✗|✔| ==================================== ==========================================
6. 結論
この記事は、各注釈の動作についてより深い洞察を提供することを目的としていました。各注釈がどのように振る舞うかを理解することは、より良い全体的なアプリケーション設計とメンテナンスに貢献するでしょう。
議論中に使用されたコードはhttps://github.com/eugenp/tutorials/tree/master/spring-core[GitHub]にあります。