Spring Framework 入門記 Beanその1 id/name属性とsingleton属性

いつまで続くか,Spring Frameworkの入門記録です.
はじめてのSpring Framework」で作成した定義ファイルでは,bean要素にname属性を指定していました.

<bean name="foo" class="study.Foo">

bean要素には,name属性の他にid属性というのもあります.「Spring Framework Reference Documentation」の「3.2.4 The bean identifiers(id and name)」によると,idBeanFactory(コンテナ)中の全てのbeanを一意に識別するものだそうです.
それではname属性はどういうもの? というと,3.2.4節には何も書かれていないのですが,「Appendix A. Spring's beans.dtd」に説明がありました.それによると,name属性はid属性の別名(alias)ということで,スペースまたはカンマで区切って複数指定できるということです.
それでは,ということで...

<bean id="akiko" name="seri wakaba" class="study.Foo">

とすると,"akiko""seri""wakaba"いずれの名前でもインスタンスを取得することが出来ました.
なお,id属性はDTDでID型として定義されているので,定義ファイル中で重複した値を記述することは出来ません(バッチリ例外が吹っ飛んできました).
一方,name属性はCDATA型なので,XMLの検証レベルでは値の重複が許されます.実際に値が重複するとどうなるのかなぁ,と思い,

<bean id="yada" name="akiko" class="study.Foo">
<bean id="wada" name="akiko" class="study.Foo">

としてみたところ,

org.springframework.beans.factory.BeanDefinitionStoreException: 
    Cannot register alias 'akiko' for bean name 'wada': 
        it's already registered for bean name 'yada'

ということで,name属性の個々の値についても,定義ファイル中で一意にしなければならないようです.
では,id属性の値とname属性の値が重複した場合はどうなるのかなぁ,と思い,

<bean id="yuri" name="ebihara" class="study.Foo">
<bean id="ebihara" name="yuri" class="study.Foo">

としてみたところ,これは問題なく通りました.ですが,自分の先入観とは異なり,name属性の方でインスタンスが引っかかりました.上の例だと,"yuri"を指定するとBeanFactoryは下の定義のインスタンス(name"yuri"の方)を返します.どうやら,BeanFactory#getBean(String)に渡した文字列(ここでは"yuri")は,それに対する別名が定義されていればその値(ここでは"ebihara")に変換され,それをキーとしてbeanのインスタンスを探すようです.
さて,BeanFactoryクラスには,保持しているbeanの名前の配列を返すgetBeanDefinitionNames()というメソッドがあります.ここでいうdefinitionNamesとはどういう名前(id or name)なのかな,ということで,

<bean id="akiko" class="study.Foo">
<bean name="yuri" class="study.Foo">
<bean id="nakama" name="yukie" class="study.Foo">

としてみたところ,"akiko""nakama""yuri"が取得できました.id属性があればその値が,なければname属性の値が採用されているようです.
ふと,id属性もname属性もない場合はどうなるのかなぁ,なんて思ったのでやってみると,beanのクラス名(完全限定名)が採用されていました.ちなみに,同一クラスの名無しのbeanを複数記述してもエラーにはならないのですが,有効な(完全限定名で取得できる)インスタンスは定義ファイル中で最後に記述したものだけになりました.上書きされるんですね.
name属性は,名前空間をクラス階層に限定するなどの付加価値もないようですし,あまり必要性を感じることができませんでした.基本的にid属性を使っていくことにします.

なんだか,全然本質的でないところでのんびりしてしまいました.とりあえず次へ行くことにします.
次は「3.2.5. To sinleton or not to singleton」です.
bean要素には,singletonという属性があります.この属性は列挙型で,trueまたはfalseを指定することが出来ます.デフォルトはtrueです.
singleton属性がtrueだと,そのbeanのインスタンスBeanFactory中に一つだけ生成され,共有されます.つまり,何度BeanFactory#getBean(String)を呼び出しても,同じインスタンスが返ってきます.
一方,singleton属性がfalseだと,BeanFactory#getBean(String)が呼び出されるたびに新しいインスタンスが返ってきます.こちらはsingletonに対してprototypeと呼ばれるようですが,Prototypeパターンが使われているということでしょうか?
なお,singletonでもprototypeでも,取得したインスタンスBeanFactoryに戻す必要はないようです.AvalonではComponentManagerから取得したインスタンスはライフサイクルに関わらず戻すのが作法だった(と思う)ので,少し落ち着かない感じがあります.Avalonの場合,Component(後にServiceと改称されてしまいました)をComponentManagerへ戻したタイミングで,ComponentManagerComponentの後処理(もしあれば)を呼び出してくれました.しかしSpring Frameworkでは,少なくともprototypeなbeanの後処理は,beanの利用者が責任を負わなくてはならないのですね.まぁ,コネクションプールなんかもそういうものですから(DataSourceから取得したConnectionは利用者がclose()する),Avalonがイレギュラーだったのかもしれません.
なんだか遅々として進んでいない感じですが,どうせ出遅れているのでじっくりと...
次回はIoC/Dependency Injectionの名前の由来らしいネタ,「3.3. Properties, collaborators, autowiring and dependency checking」に取り組みたいと思います.