@Autowired を使用する

このセクションに含まれる例では、Spring の @Autowired アノテーションの代わりに JSR 330 の @Inject アノテーションを使用できます。詳細については、こちらを参照してください。

次の例に示すように、@Autowired アノテーションをコンストラクターに適用できます。

  • Java

  • Kotlin

public class MovieRecommender {

	private final CustomerPreferenceDao customerPreferenceDao;

	@Autowired
	public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
		this.customerPreferenceDao = customerPreferenceDao;
	}

	// ...
}
class MovieRecommender @Autowired constructor(
	private val customerPreferenceDao: CustomerPreferenceDao)

Spring Framework 4.3 以降、ターゲット Bean が最初にコンストラクターを 1 つだけ定義している場合、そのようなコンストラクターに対する @Autowired アノテーションは必要なくなりました。ただし、複数のコンストラクターが使用可能で、プライマリ / デフォルトコンストラクターがない場合は、どれを使用するかをコンテナーに指示するために、少なくとも 1 つのコンストラクターに @Autowired アノテーションを付ける必要があります。詳細については、コンストラクターの解決に関する説明を参照してください。

次の例に示すように、@Autowired アノテーションを従来の setter メソッドに適用することもできます。

  • Java

  • Kotlin

public class SimpleMovieLister {

	private MovieFinder movieFinder;

	@Autowired
	public void setMovieFinder(MovieFinder movieFinder) {
		this.movieFinder = movieFinder;
	}

	// ...
}
class SimpleMovieLister {

	@set:Autowired
	lateinit var movieFinder: MovieFinder

	// ...

}

次の例に示すように、任意の名前と複数の引数を持つメソッドにアノテーションを適用することもできます。

  • Java

  • Kotlin

public class MovieRecommender {

	private MovieCatalog movieCatalog;

	private CustomerPreferenceDao customerPreferenceDao;

	@Autowired
	public void prepare(MovieCatalog movieCatalog,
			CustomerPreferenceDao customerPreferenceDao) {
		this.movieCatalog = movieCatalog;
		this.customerPreferenceDao = customerPreferenceDao;
	}

	// ...
}
class MovieRecommender {

	private lateinit var movieCatalog: MovieCatalog

	private lateinit var customerPreferenceDao: CustomerPreferenceDao

	@Autowired
	fun prepare(movieCatalog: MovieCatalog,
				customerPreferenceDao: CustomerPreferenceDao) {
		this.movieCatalog = movieCatalog
		this.customerPreferenceDao = customerPreferenceDao
	}

	// ...
}

次の例に示すように、@Autowired をフィールドにも適用し、コンストラクターと組み合わせることもできます。

  • Java

  • Kotlin

public class MovieRecommender {

	private final CustomerPreferenceDao customerPreferenceDao;

	@Autowired
	private MovieCatalog movieCatalog;

	@Autowired
	public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
		this.customerPreferenceDao = customerPreferenceDao;
	}

	// ...
}
class MovieRecommender @Autowired constructor(
	private val customerPreferenceDao: CustomerPreferenceDao) {

	@Autowired
	private lateinit var movieCatalog: MovieCatalog

	// ...
}

ターゲットコンポーネント(たとえば、MovieCatalog または CustomerPreferenceDao)が、@Autowired アノテーション付きインジェクションポイントに使用する型によって一貫して宣言されていることを確認してください。そうしないと、実行時に「型の一致が見つかりません」というエラーが原因でインジェクションが失敗する可能性があります。

クラスパススキャンを介して検出された XML 定義の Bean またはコンポーネントクラスの場合、コンテナーは通常、事前に具象型を認識します。ただし、@Bean ファクトリメソッドの場合、宣言された戻り値の型が十分に表現力があることを確認する必要があります。複数のインターフェースを実装するコンポーネント、または実装型によって潜在的に参照されるコンポーネントの場合、ファクトリメソッドで最も具体的な戻り値型を宣言することを検討してください(少なくとも Bean を参照するインジェクションポイントで必要とされる特定の)。

4.3 以降、@Autowired は注入時に自己参照 (つまり、現在注入されている Bean への参照) も考慮します。自己注入はフォールバックであることに注意してください。実際には、自己参照は最後の手段としてのみ使用してください (たとえば、Bean のトランザクションプロキシを介して同じインスタンス上の他のメソッドを呼び出す場合など)。このようなシナリオでは、影響を受けるメソッドを別のデリゲート Bean に分離することを検討してください。

次の例に示すように、ApplicationContext から特定の型のすべての Bean を提供するように Spring に指示して、@Autowired アノテーションをその型の配列を想定するフィールドまたはメソッドに追加することもできます。

  • Java

  • Kotlin

public class MovieRecommender {

	@Autowired
	private MovieCatalog[] movieCatalogs;

	// ...
}
class MovieRecommender {

	@Autowired
	private lateinit var movieCatalogs: Array<MovieCatalog>

	// ...
}

次の例に示すように、型付きコレクションにも同じことが当てはまります。

  • Java

  • Kotlin

public class MovieRecommender {

	private Set<MovieCatalog> movieCatalogs;

	@Autowired
	public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
		this.movieCatalogs = movieCatalogs;
	}

	// ...
}
class MovieRecommender {

	@Autowired
	lateinit var movieCatalogs: Set<MovieCatalog>

	// ...
}

配列またはリスト内の項目を特定の順序でソートする場合、ターゲット Bean は org.springframework.core.Ordered インターフェースを実装するか、@Order または標準 @Priority アノテーションを使用できます。それ以外の場合、それらの順序は、コンテナー内の対応するターゲット Bean 定義の登録順序に従います。

@Order アノテーションは、ターゲットクラスレベルおよび @Bean メソッドで、個々の Bean 定義に対して宣言できます(同じ Bean クラスを使用する複数の定義の場合)。@Order 値は、インジェクションポイントの優先順位に影響を与える可能性がありますが、依存関連と @DependsOn 宣言によって決定される直交の懸念であるシングルトンの起動順序には影響しないことに注意してください。

構成クラスの @Order アノテーションは、起動時の構成クラスの全体的なセット内の評価順序にのみ影響することに注意してください。このような構成レベルの順序値は、含まれる @Bean メソッドにはまったく影響しません。Bean レベルの順序付けの場合、各 @Bean メソッドには、特定の Bean 型 (ファクトリメソッドによって返される) の複数の一致のセット内で適用される独自の @Order アノテーションが必要です。

標準の jakarta.annotation.Priority アノテーションは、メソッドで宣言できないため、@Bean レベルでは使用できないことに注意してください。そのセマンティクスは、各型の単一 Bean で @Primary と組み合わせて @Order 値を介してモデル化できます。

予想されるキー型が String である限り、型された Map インスタンスでさえオートワイヤーできます。次の例に示すように、マップ値には予想される型のすべての Bean が含まれ、キーには対応する Bean 名が含まれます。

  • Java

  • Kotlin

public class MovieRecommender {

	private Map<String, MovieCatalog> movieCatalogs;

	@Autowired
	public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
		this.movieCatalogs = movieCatalogs;
	}

	// ...
}
class MovieRecommender {

	@Autowired
	lateinit var movieCatalogs: Map<String, MovieCatalog>

	// ...
}

デフォルトでは、特定のインジェクションポイントに一致する候補 Bean がない場合、オートワイヤーは失敗します。宣言された配列、コレクション、マップの場合、少なくとも 1 つの一致する要素が期待されます。

デフォルトの動作では、アノテーション付きのメソッドとフィールドを必要な依存関係を示すものとして扱います。次の例に示すように、この動作を変更して、フレームワークが不必要なものとしてマークすることで不満足なインジェクションポイントをスキップできるようにします(つまり、@Autowired の required 属性を false に設定することにより)。

  • Java

  • Kotlin

public class SimpleMovieLister {

	private MovieFinder movieFinder;

	@Autowired(required = false)
	public void setMovieFinder(MovieFinder movieFinder) {
		this.movieFinder = movieFinder;
	}

	// ...
}
class SimpleMovieLister {

	@Autowired(required = false)
	var movieFinder: MovieFinder? = null

	// ...
}

依存関係(または、複数の引数の場合はその依存関係の 1 つ)が利用できない場合、非必須メソッドはまったく呼び出されません。このような場合、必須ではないフィールドはまったく入力されず、デフォルト値がそのまま残ります。

つまり、required 属性を false に設定すると、対応するプロパティがオートワイヤーの目的でオプションであり、オートワイヤーできない場合はプロパティが無視されることを示します。これにより、依存性注入を介してオプションでオーバーライドできるデフォルト値をプロパティに割り当てることができます。

@Autowired の required 属性は、複数のコンストラクターを処理する可能性のある Spring のコンストラクター解決アルゴリズムのために、注入されたコンストラクターとファクトリメソッドの引数は特別な場合があります。コンストラクターとファクトリメソッドの引数はデフォルトで効果的に必要ですが、単一のコンストラクターシナリオでは、一致する Bean が利用できない場合に空のインスタンスに解決する複数要素のインジェクションポイント(配列、コレクション、マップ)などのいくつかの特別なルールがありますこれにより、すべての依存関係を一意の複数引数コンストラクターで宣言できる共通の実装パターンが可能になります。たとえば、@Autowired アノテーションなしで単一の public コンストラクターとして宣言できます。

特定の Bean クラスの 1 つのコンストラクターのみが、required 属性を true に設定して @Autowired を宣言できます。これは、Spring Bean として使用される場合にオートワイヤーするコンストラクターを示します。その結果、required 属性がデフォルト値の true のままである場合、@Autowired でアノテーションを付けられるコンストラクターは 1 つだけです。複数のコンストラクターがアノテーションを宣言する場合、すべてオートワイヤーの候補と見なされるために required=false を宣言する必要があります(XML の autowire=constructor に類似)。Spring コンテナー内の Bean を一致させることで満たすことができる依存関係の数が最も多いコンストラクターが選択されます。どの候補も満たすことができない場合は、プライマリ / デフォルトコンストラクター(存在する場合)が使用されます。同様に、クラスが複数のコンストラクターを宣言しているが、それらのいずれにも @Autowired アノテーションが付いていない場合、プライマリ / デフォルトコンストラクター(存在する場合)が使用されます。クラスが最初に単一のコンストラクターのみを宣言する場合、アノテーションが付けられていなくても、常に使用されます。アノテーション付きコンストラクターはパブリックである必要はないことに注意してください。

または、次の例に示すように、Java 8 の java.util.Optional を使用して、特定の依存関係の不要な性質を表現できます。

public class SimpleMovieLister {

	@Autowired
	public void setMovieFinder(Optional<MovieFinder> movieFinder) {
		...
	}
}

Spring Framework 5.0 の時点で、@Nullable アノテーション (任意のパッケージ内の任意の種類 — たとえば、JSR-305 の javax.annotation.Nullable ) を使用するか、Kotlin 組み込みの null 安全サポートを利用することもできます。

  • Java

  • Kotlin

public class SimpleMovieLister {

	@Autowired
	public void setMovieFinder(@Nullable MovieFinder movieFinder) {
		...
	}
}
class SimpleMovieLister {

	@Autowired
	var movieFinder: MovieFinder? = null

	// ...
}

よく知られている解決可能な依存関係であるインターフェースに @Autowired を使用することもできます: BeanFactoryApplicationContextEnvironmentResourceLoaderApplicationEventPublisherMessageSource。これらのインターフェースと、ConfigurableApplicationContext や ResourcePatternResolver などの拡張インターフェースは、特別な設定を必要とせずに自動的に解決されます。次の例では、ApplicationContext オブジェクトをオートワイヤーします。

  • Java

  • Kotlin

public class MovieRecommender {

	@Autowired
	private ApplicationContext context;

	public MovieRecommender() {
	}

	// ...
}
class MovieRecommender {

	@Autowired
	lateinit var context: ApplicationContext

	// ...
}

@Autowired@Inject@Value@Resource アノテーションは、Spring BeanPostProcessor 実装によって処理されます。つまり、これらのアノテーションを独自の BeanPostProcessor または BeanFactoryPostProcessor 型(存在する場合)内に適用することはできません。これらの型は、XML または Spring @Bean メソッドを使用して明示的に「接続」する必要があります。