BeanFactory

XMLのBeanの定義についてちょっと触ったのでメモ。

インスタンスの生成

Beanを生成する為の仕組みとしては3パターン程用意されているみたいでげす。ひっく!

  1. コンストラクタによるビーン生成
  2. 静的ファクトリメソッドによるビーン生成
  3. 動的ファクトリメソッドによるビーン生成

コンストラクタによるビーン生成

これは、引数のないコンストラクタを呼び出して、インスタンスを生成する場合。
一番シンプルなやり方です。

<bean id="exampleBean"
      class="examples.ExampleBean"/>
<bean name="anotherExample"
      class="examples.ExampleBeanTwo"/> 

静的ファクトリメソッドによるビーン生成

これは、静的なメソッドを呼び出して、インスタンスを生成する場合。

public class ExampleBean2 {
    public static Object createInstance() {
        return new String("HelloWorld!");
    }
}


みたいなクラスを作って、XMLの定義は以下のようになります。

<bean id="exampleBean"
      class="examples.ExampleBean2"
      factory-method="createInstance"/>

動的ファクトリメソッドによるビーン生成

これは、動的なメソッドを呼び出して、インスタンスを生成する場合。

public class ExampleBean3 {
    public Object createInstance() {
        return new String("HelloWorld!");
    }
}


みたいなクラスを作って、XMLの定義は以下のようになります。

<bean id="factory" class="examples.FactoryBean"/>
<bean id="exampleBean"
      factory-bean="factory"
      factory-method="createInstance"/>

【メモ】
存在しないクラスをXMLへ定義してみたところ、実行時にClassNotFoundExceptionがthrowされました。
これって、XMLのロード時にクラスもロードしてるってこと?
しばらくしたらわかるかな?
とりあえずメモ!

ビーン識別子(IDと名前)

Beanにはid属性とは別にエイリアス(name属性)をつけることができます。
ここで気をつけたいのは、2つビーンが定義されており(AとB)、Aのid属性とBのname属性が同じ値の場合に
getBean()すると、name属性の方が優先され、Bのビーンが取得されます。
なんか変なの!!!

シングルトン属性

デフォルトでは、シングルトンモードでビーンは管理される。
つまり、同一idでgetBean()した場合、同一インスタンスへの参照が毎回返却される。
そうではなく、getBean()する度にインスタンスを生成したい場合は、singleton属性へfalseを設定する。


singleton属性について以下のように書いてあるが良くわかりません!

注:プロトタイプモードでビーンをデプロイする場合、ビーンのライフサイクルは若干変更される。定義によって、Springは非シングルトン/プロトタイプビーンのライフサイクルを完全に管理することはできない。生成された後、クライアントに渡され、コンテナはその跡を追いかけるようなことはしないからだ。非シングルトン/プロトタイプビーンを「new」オペレータの置き換えとして話をするとSpringの役割を考えることができる。そのポイントを経過したライフサイクルの様相はクライアントで処理されなければならないのだ。

ビーンプロパティの設定とコラボレータ


Dependency Injectionの基本原理は、ビーン間の依存性(つまり、いっしょに動作する他のオブジェクト)をコンストラクタ引数か、ファクトリメソッドへの引数、あるいは生成後のオブジェクトインスタンスあるいはファクトリメソッドから返されたオブジェクトインスタンスに設定されるプロパティでしか定義しないということだす。
Springでは、メソッド・インジェクションとコンストラクタ・インジェクションの2つをサポートしている。

メソッド・インジェクション

ただの文字列なので理解しづらいが、この場合、以下のようにしてPersonオブジェクトとStringオブジェクトの
依存性をコンフィグレーションで定義し、ビーン間の関係を疎結合としている。
SetterベースのDIでは、property属性を利用する。

 <!-- メソッドインジェクションのテスト -->
 <bean id="person" class="chapter01.Person">
   <property name="name"><value>Tom</value></property>
 </bean>
コンストラクタ・インジェクション

以下のように、constructor-arg属性を利用してコンストラクタ引数を渡している。

<!-- コンストラクターインジェクションのテスト -->
 <bean id="person2" class="chapter01.Person">
  <constructor-arg>
   <value>Jason</value>
  </constructor-arg>
  <constructor-arg>
   <ref bean="group"></ref>
  </constructor-arg>
 </bean>
 <bean id="group" class="chapter01.Group">
  <property name="name"><value>システム開発部</value></property>
 </bean>


ちなみにファクトリメソッドへ引数を渡してあげる場合は、constructor-arg属性を利用します。
ここでは端折ります。

【補足】
コンストラクタ引数の型や順番を指定することができます。
1.コンストラクタ引数の型を指定する。
(typeへ指定するクラス名はパッケージ名も必要なので注意)

<!-- コンストラクターインジェクションのテスト -->
 <bean id="person2" class="chapter01.Person">
  <constructor-arg type="java.lang.String">
   <value>Jason</value>
  </constructor-arg>
  <constructor-arg type="chapter01.Group">
   <ref bean="group"></ref>
  </constructor-arg>
 </bean>


2.コンストラクタ引数の順番を指定する。
(indexは0から始まるので注意)

<!-- コンストラクターインジェクションのテスト -->
 <bean id="person2" class="chapter01.Person">
  <constructor-arg index="0">
   <value>Jason</value>
  </constructor-arg>
  <constructor-arg index="1">
   <ref bean="group"></ref>
  </constructor-arg>
 </bean>
ビーンプロパティとコンストラクタ引数の詳細

ビーンプロパティやコンストラクタ引数へ他の管理されたビーンへのリファレンスやインラインで定義された値
を設定することができます。

1.value要素
  人が判読可能な文字列表現としてプロパティやコンストラクタ引数を指定できます。


2.null要素
  null値を扱うのに用います。空のvalue要素を使った場合、空文字(0byte文字)が設定されます。


3.list要素
  Listインスタンスを設定します。

  <property name="someList">
    <list>
      <value>a list element followed by a reference</value>
      <ref bean="myDataSource"/>
    </list>
  </property>
||<  


4.set要素
  Setインスタンスを設定します。
>||
  <property name="someSet">
    <set>
      <value>just some string</value>
      <ref bean="myDataSource"/>
    </set>
  </property>


5.map要素
  Mapインスタンスを設定します。

  <property name="someMap">
      <map>
          <entry key="yup an entry">
              <value>just some string</value>
          </entry>
          <entry key="yup a ref">
              <ref bean="myDataSource"/>
          </entry>
      </map>
  </property>
||<  


6.props要素
  Propertiesインスタンスを設定します。
>||
  <property name="people">
      <props>
          <prop key="HarryPotter">The magic property</prop>
          <prop key="JerrySeinfeld">The funny property</prop>
      </props>
  </property>


7.bean要素
  property要素内部のbean要素はBeanFactoryのどこかで定義されたビーンを参照する代わりにビーンの値をインラインに定義するのに用いる。
  このインラインビーン定義には定義済みのidを指定しなくてもよい。

  <property name="target">
      <bean class="com.mycompany.PersonImpl">
          <property name="name"><value>Tony</value></property>
          <property name="age"><value>51</value></property>
      </bean>
  </property>


8.idref要素
  idrefタグを使っていることで、Springがデプロイ時に、他のビーンが実際に存在していることを検証できるらしい。。。
  よくわかりません。。。


9.ref要素
  指定されたプロパティの値へコンテナで管理されているほかのビーンの参照を指定する


id属性かあるいはname属性が一致するビーンへの参照を指定する。

<ref bean="someBean"/>


同じファイルにあるXMLのid属性と一致するビーンへの参照を指定する。
同じファイルの中にマッチする要素が見つからない場合、XMLパーサはエラーを検出する為、検証に利用できる。

<ref local="someBean"/>


カレントのBeanFactory(もしくはApplicationContext)の親のBeanFactory(もしくAplicationContext)にあるビーンへの参照を指定する。

<ref parent="someBean"/>

depends-onを使う

あるビーンを生成する際に、事前に別のビーンが生成されている必要がある場合、
depends-on属性を利用することで、ビーンの生成順序をコントロールすることが出来る。