spring依存注入配置の詳細


Technoratiマーク:spring、依存注入、ioc
    前回のspring依存注入に続き、spring依存注入の方式(ビルダー注入、set注入、静的工場注入と実例的工場注入)を説明しました.今回はspring依存注入配置ファイルに深く入りました.
    sprint依存注入方式では、依存対象と基本値(基本データタイプとString値)を注入するためにを使用することが分かる.様々な値の配置について詳しく説明します.
一、基本値(基本データタイプとString)
    xml設定ファイルでは、属性「value」を使ってパラメータの値を指定します.ちなみに、javaBensのPropertyEditorsはこれらのstring値を対応するデータタイプに変換します.
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" 
                           destroy-method="close">
 <!-- setDriverClassName(String)      -->
 <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
 <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
 <property name="username" value="root"/>
 <property name="password" value="123"/>
</bean>
    p名前空間を使って、より簡潔な構成を見てみます.
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     <!--   p      �C>
     xmlns:p="http://www.springframework.org/schema/p"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans.xsd">

 <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
      destroy-method="close"
      p:driverClassName="com.mysql.jdbc.Driver"
      p:url="jdbc:mysql://localhost:3306/mydb"
      p:username="root"
      p:password="masterkaoli"/>
</beans>
    p名前空間を使って配置を簡略化しましたが、ある程度足りないところがあります.スペルミスを再実行する必要があります.デザイン時には分かりません.もちろんIDEAやspringSourceなどのコード提示機能があるIDEを使えば、これらのミスを避けることができます.他にも、propertyを配置する方法があります.下にjava.util.ProPertiesを設定します.
<bean id="mappings"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
 <property name="properties">
    <value>
       jdbc.driver.className=com.mysql.jdbc.Driver
       jdbc.url=jdbc:mysql://localhost:3306/mydb
    </value>
 </property>
</bean>
    上記のような構成は提唱に値するものであり、属性valueを用いて構成するのではなく、<value/>を使用して値を設定する.
二、元素idref
    idref要素は、容器内の他のbeanのidをまたは要素に送るために使用され、同時にエラー検証機能を提供します.
<bean id="theTargetBean" class="..."/>
<bean id="theClientBean" class="...">
    <property name="targetName">
        <idref bean="theTargetBean" />
    </property>
</bean>
    上記のbeanの定義は以下の構成に等しい.
<bean id="theTargetBean" class="..." />
<bean id="client" class="...">
    <property name="targetName" value="theTargetBean" />
</bean> 
    第一の方法を推奨します.idrefは容器が配備時に「theTarget Bean」の検証を提供しています.第二の方法を使うと、clientが初期化された時に発見されます.特にこのclientはprototypeです.容器が初期化されてから長い時間が必要です.
    また、インデックスのbeanも同じxmlプロファイルにある場合は、属性localを使用して、xmlの解釈器より早くこのbeanのidを確認することができます.
<property name="targetName">
 <!-- id  theTargetBean  bean    ,        -->
 <idref local="theTargetBean"/>
</property>
三、他のbeanの索引(依存対象)
    「constructor-arg/」または「property/」の要素の内部では、ref要素も使用できます.beanで指定された属性の値を容器の中のもう一つのbeanへの参照として設定します.refには三つの属性bean、local、parentがあります.その具体的な違いは以下の通りです.
四、内部bean
    <constructor-arg/>または<property/>要素の内部で<bean/>を使用して内部beanを定義することもできます.
<bean id="outer" class="...">
<!--                ,        bean -->
 <property name="target">
  <bean class="com.example.Person"> <!--   bean -->
    <property name="name" value="Fiona Apple"/>
    <property name="age" value="25"/>
  </bean>
 </property>
</bean>
    注意したいのは、内部のbeanの定義では、IDやname属を指定する必要はなく、scopeを指定する必要もなく、これらは自動的に容器に無視されます.内部のbeanの作成はouterbeanの作成に伴って作成されます.
五、コレクション
     Java collection内のList、Set、Map、Proptiesの値は、以下のように設定するために、要素を使用して使用することができます.
<bean id="moreComplexObject" class="example.ComplexObject">
 <!--      setAdminEmails(java.util.Properties)-->
 <property name="adminEmails">
  <props>
      <prop key="administrator">[email protected]</prop>
      <prop key="support">[email protected]</prop>
      <prop key="development">[email protected]</prop>
  </props>
 </property>
 <!--      setSomeList(java.util.List)-->
 <property name="someList">
  <list>
      <value>a list element followed by a reference</value>
      <ref bean="myDataSource" />
  </list>
 </property>
 <!--      setSomeMap(java.util.Map)-->
 <property name="someMap">
  <map>
      <entry key="an entry" value="just some string"/>
      <entry key ="a ref" value-ref="myDataSource"/>
  </map>
 </property>
 <!--      setSomeSet(java.util.Set)-->
 <property name="someSet">
  <set>
      <value>just some string</value>
      <ref bean="myDataSource" />
  </set>
 </property>
</bean>
    注意したいのは、Mapのkeyやvalueにおいて、Setのvalueは、以下のような要素を使ってもいいです.
bean | ref | idref | list | set | map | props | value | null
六、コレクション合併
    spring容器もCollectionの統合をサポートしています.私たちは父要素の中でを定義して、次に子要素の中でを定義します.は父要素の集合を継承またはカバーします.その結果、子要素の中に父、次のようなCollectionの集合があります.
<beans>
 <bean id="parent" abstract="true" class="example.ComplexObject">
  <property name="adminEmails">
      <props>
          <prop key="administrator">[email protected]</prop>
          <prop key="support">[email protected]</prop>
      </props>
  </property>
 </bean>
 <bean id="child" parent="parent">
  <property name="adminEmails">
      <!--           merge   true-->
      <props merge="true">
          <prop key="sales">[email protected]</prop>
          <prop key="support">[email protected]</prop>
      </props>
  </property>
 </bean>
<beans>
    注意サブ要素に「merge=true」を設置していますが、その上で合併した結果は以下の通りです.
[email protected]
[email protected]
[email protected]
    父要素からを継承し、その中のsupportの要素をカバーしました.
    同様に、も同様の用法を持っていますが、元素に使用されると、その内元素の順序は依然として保持されています.親要素のリストはすべてのサブ要素のリストの前にあります.Set、Map、Prop tiesは要素の順序問題がありません.
七、コレクション合併の制限
    統合Collectionでは、タイプが一致しないCollection(SetやListなど)を統合することはできません.また、例外を出す必要がある場合は、サブ要素の異常は親要素の異常なサブクラスでなければなりません.親要素に「merge=true」を設定していれば、希望する統合効果は得られません.
八、汎型集合
    java 5の後には、汎型集合が使用されます.springのタイプ変換機構は、このような汎型集合の使用をサポートしています.以下の通りです.
public class Foo {
  private Map<String, Float> accounts;
  public void setAccounts(Map<String, Float> accounts) {
      this.accounts = accounts;
  }
}
   xmlプロファイルは以下の通りです.
<beans>
  <bean id="foo" class="x.y.Foo">
      <property name="accounts">
          <map>
              <entry key="one" value="9.99"/>
              <entry key="two" value="2.75"/>
              <entry key="six" value="3.99"/>
          </map>
      </property>
  </bean>
</beans>
   fooを注入する必要がある場合、Map<String、Float>の汎型情報は反射によって得られます.springのタイプ変換機構は属性valueの値を識別することができます.Floatタイプのものはその後、Stringタイプの「9.99,2.75,3.99」をStringタイプに変換します.
九、nullと空の文字列の値
    以下の例では、「email」は空の文字列(")に設定されます.
<bean class="ExampleBean">
 <property name="email" value=""/>
</bean>
    上記の例はjavaコードと同じです.exampleBeabin.setEmail(')は同様で、null値の設定方法を見てください.
<bean class="ExampleBean">
 <property name="email"><null/></property>
</bean>
       上記の例は、javaコードと同じです.exampleBeans.setEmail(null)
十、p名前空間と配置の簡略化
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  <!--    p      -->
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean name="classic" class="com.example.ExampleBean">
      <property name="email" value="[email protected]"/>
  </bean>

  <bean name="p-namespace" class="com.example.ExampleBean"
        p:email="[email protected]"/>
</beans>
   上に示すように、p名前空間の使用を実証し、より深く見ると、p名前空間を使用して依存オブジェクトを指す場合:
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean name="john-classic" class="com.example.Person">
      <property name="name" value="John Doe"/>
      <property name="spouse" ref="jane"/>
  </bean>
  <bean name="john-modern"
      class="com.example.Person"
      p:name="John Doe"
      p:spouse-ref="jane"/>
  <bean name="jane" class="com.example.Person">
      <property name="name" value="Jane Doe"/>
  </bean>
</beans>
    上記のように、従来の使用法とp名前空間を用いたインデックスがbean janeに向けられていることを示し、従来の使用法は「property name=「spouse」ref=「jane」であり、p名前空間ではp:spouse-ref=「jane」であり、-refではspouseは基本的なデータタイプまたはStringではなく、インデックスであると説明している.
十一、c名前空間
    p名前空間は<property/>の構成を簡略化するために使用され、同様に、c名前空間は<constructor-arg/>の構成を簡略化するために使用されることができる.
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:c="http://www.springframework.org/schema/c"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean id="bar" class="x.y.Bar"/>
  <bean id="baz" class="x.y.Baz"/>
  <--         -->
  <bean id="foo" class="x.y.Foo">
      <constructor-arg ref="bar"/>
      <constructor-arg ref="baz"/>
      <constructor-arg value="[email protected]"/>
  </bean>
  <--    c        -->
  <bean id="foo" class="x.y.Foo" c:bar-ref="bar" c:baz-ref="baz" c:email="[email protected]">
</beans>
    c名前空間を使ったインデックス応用も見てください.同じように-refを使って、
<bean id="foo" class="x.y.Foo" c:_0-ref="bar" c:_1-ref="baz">
十二、複合属性名
    下のような構成を見ることがあります.
<bean id="foo" class="foo.Bar">
 <property name="fred.bob.sammy" value="123" />
</bean>
    上記のような「property/」は複合属性の名前アプリケーションですが、どうやって理解しますか?bean fooの理由にはproperty fredがあります.同じようにproperty fredにproperty bobがあります.propertybobにはproperty sammyがあります.最後に「123」になります.sammyに値を与えます.上記の操作をしてもいいです.fredとbobは全部空にしてはいけません.13、depends-onを使います.
    あるbeanを創建する前に、他のbeanを創建する必要があります.この時には、プロパティdepends-onを使う必要があります.
<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />
    depends-onを使用して、beanOneを実際化する前に、managerを具体化する必要があります.では、どのように先に複数のbeanを具体化しますか?カンマ、セミコロン、スペースを使って別れます.以下の通りです.
<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
 <property name="manager" ref="manager" />
</bean>
<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />
    以上のように、これはbeanOneを実装する前に、managerとaccountDaoを具体化する必要があります.
14、lazy-initを使用する
    Appleication Comptextで実現されるデフォルトの行為は、起動時にすべてのsingleton beanを事前に実例化することである(つまり注入に依存する).このようなデフォルトの処理方法はあなたが望んでいるものではありません.必要な時に実際化してほしいです.すなわち、初めて容器にgetBenを通してbeanを要求する時に初めて実用化されます.このような方法は「怠惰負荷」といいます.属性lazy-nitを使うとこの効果が達成できます.
<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true"/>
    注意すべきは、lazy-nit設定はscop属性がsingletonのbeanのみに作用します.また、コンテナレベルでは要素に'default-lazy-nit'属性を使用して遅延初期化を制御することも可能です.   
<beans default-lazy-init="true">
  <!--   bean       -->
</beans>
     一つのbeanのscope属性がscope=「pototype」の場合、lazy-nit=「false」が設定されていても、容器起動時にはbeanを実装せず、getBenメソッドを呼び出すのが実用化されます.