springframework

web.xmlで設定していないBean構成クラスをオートワイヤーで使用できる理由

参考書籍:SpringFramework5 プログラミング入門 (著:掌田 津耶乃)

目的

上記書籍の写経でなんで動くかわからなかった部分を調べたのでメモ

背景

Springではインスタンス生成箇所と使用箇所を切り分けられるらしい。
@Autowiredアノテーションを使用すれば変数宣言だけでインスタンス生成できるらしい。
準備としては以下の通りやれば良いらしい。
※application-configを使用しないパターンの話

1.オートワイヤーしたいクラスを作成する。
2.Bean構成クラスを作成する(オートワイヤーしたいクラスをreturnする処理を持つクラス)
3.web.xmlでBean構成クラスをcontext-paramタグの値として設定する。
4.[1]を利用したいクラスで変数に@Autowiredアノテーションを付与すればOK

疑問

書籍の中で、以下のような実装があった。

1.クラスAについて、Bean構成クラスを用意してweb.xmlに設定する。
2.クラスAをサーブレットでオートワイヤーして使用する。
3.[2]で作成されたクラスAインスタンスから別クラスBを呼び出す。

[1]でやっているweb.xmlへの設定について、B用のBean構成クラスを指定しても同じように動作する。(!?)

だったらweb.xmlの設定に意味ないのかと、でたらめな値を設定すると
「Bean構成ファイルが見つからない」旨の500エラーが返ってくる。

どこにもクラスAに関するBean構成クラスへのアクセスパスは記述していないのに……。

理由

Bean構成クラスには2種類のアノテーションを付与している。
1.@Configuration
2.@ComponentScan(<パッケージ>)

このうち、2にはBean構成クラスを含むパッケージ(A用、B用の構成クラスが属している)を指定している。
もしやと思い、クラスB用のBean構成クラスで@ComponentScanを外してみた。

結果:500エラー(構成ファイルが見つからない)

どうやら、

1.サーブレットで@Autowire付与のクラスが見つかる。
2.web.xmlで構成クラスを探し、アクセスする。
3.構成クラスが読み込まれる際、@ComponentScanの引数から@Beanアノテーションを検索する。
4.web.xmlに設定されたファイル以外でも、対象の@Beanアノテーションがあればロードする。

という順序で動くため、web.xmlで設定していないBean構成クラスが有効に動作したらしい。

結論

web.xmlはオートワイヤーの入口で、実際の指定先は@ComponentScanの引数に含まれていれば良い。
※構成クラス側では@Bean、オートワイヤー対象側では@Componentが付与されている前提。

よく読んだら

P141の@ComponentScan項目にそれらしいことが書いてあった。