依存関係と構成の詳細
前のセクションで説明したように、Bean プロパティとコンストラクター引数は、他のマネージド Bean (コラボレーター) への参照として、またはインラインで定義された値として定義できます。Spring の XML ベースの構成メタデータは、この目的のために、<property/>
要素および <constructor-arg/>
要素内のサブ要素型をサポートします。
ストレート値 (プリミティブ、文字列など)
<property/>
要素の value
属性は、プロパティまたはコンストラクター引数を人間が判読できる文字列表現として指定します。Spring の変換サービスは、これらの値を String
からプロパティまたは引数の実際の型に変換するために使用されます。次の例は、設定されるさまざまな値を示しています。
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- results in a setDriverClassName(String) call -->
<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="misterkaoli"/>
</bean>
次の例では、さらに簡潔な XML 構成に p-namespace を使用しています。
<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
https://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="misterkaoli"/>
</beans>
上記の XML はより簡潔です。ただし、Bean 定義を作成するときにプロパティの自動補完をサポートする IDE(Pleiades All in One (JDK, STS, Lombok 付属) または Eclipse 用 Spring Tools (英語) 、IntelliJ IDEA (英語) など)を使用しない限り、設計時ではなく実行時に型ミスが検出されます。このような IDE の支援を強くお勧めします。
次のように、java.util.Properties
インスタンスを構成することもできます。
<bean id="mappings"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<!-- typed as a java.util.Properties -->
<property name="properties">
<value>
jdbc.driver.className=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
</value>
</property>
</bean>
Spring コンテナーは、JavaBeans PropertyEditor
メカニズムを使用して、<value/>
エレメント内のテキストを java.util.Properties
インスタンスに変換します。これは便利なショートカットであり、Spring チームが value
属性スタイルよりもネストされた <value/>
要素の使用を好む数少ない場所の 1 つです。
idref
要素
idref
要素は、コンテナー内の別の Bean の id
(文字列値 - 参照ではない)を <constructor-arg/>
または <property/>
要素に渡すための単なるエラー防止方法です。次の例は、その使用方法を示しています。
<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
タグを使用すると、参照される Bean という名前が実際に存在するかどうかをコンテナーが デプロイ時に検証できるため、最初の形式が 2 番目の形式よりも推奨されます。2 番目のバリエーションでは、client
Bean の targetName
プロパティに渡される値に対して検証は実行されません。型ミスは、client
Bean が実際にインスタンス化されるときにのみ発見されます (おそらく致命的な結果を伴います)。client
Bean がプロトタイプ Bean である場合、この型ミスとその結果生じる例外は、コンテナーがデプロイされてからかなり経ってから初めて発見される可能性があります。
idref エレメントの local 属性は、通常の bean 参照を超える値を提供しないため、4.0 Bean XSD ではサポートされなくなりました。4.0 スキーマにアップグレードするときに、既存の idref local 参照を idref bean に変更します。 |
<idref/>
要素が価値をもたらす一般的な場所(少なくとも Spring 2.0 より前のバージョン)は、ProxyFactoryBean
Bean 定義の AOP インターセプターの構成にあります。インターセプター名を指定するときに <idref/>
要素を使用すると、インターセプター ID のスペルミスを防ぐことができます。
他の Bean への参照 (コラボレーター)
ref
要素は、<constructor-arg/>
または <property/>
定義要素内の最後の要素です。ここでは、Bean の指定されたプロパティの値を、コンテナーによって管理される別の Bean(コラボレーター)への参照に設定します。参照される Bean は、プロパティが設定される Bean の依存関係であり、プロパティが設定される前に必要に応じて初期化されます。(コラボレーターがシングルトン Bean である場合、コンテナーによってすでに初期化されている可能性があります)すべての参照は、最終的には別のオブジェクトへの参照です。スコープと検証は、bean
属性または parent
属性を介して他のオブジェクトの ID または名前を指定するかどうかによって異なります。
<ref/>
タグの bean
属性を介してターゲット Bean を指定するのが最も一般的な形式であり、同じ XML ファイル内にあるかどうかに関係なく、同じコンテナーまたは親コンテナー内の Bean への参照を作成できます。bean
属性の値は、ターゲット Bean の id
属性と同じでも、ターゲット Bean の name
属性の値の 1 つと同じでもかまいません。次の例は、ref
要素の使用方法を示しています。
<ref bean="someBean"/>
parent
属性を介してターゲット Bean を指定すると、現在のコンテナーの親コンテナーにある Bean への参照が作成されます。parent
属性の値は、ターゲット Bean の id
属性またはターゲット Bean の name
属性の値のいずれかと同じである場合があります。ターゲット Bean は、現在のコンテナーの親コンテナーに存在する必要があります。この Bean 参照バリアントは、主にコンテナーの階層があり、親 Bean と同じ名前のプロキシで親コンテナー内の既存の Bean をラップする場合に使用する必要があります。次のリストのペアは、parent
属性の使用方法を示しています。
<!-- in the parent context -->
<bean id="accountService" class="com.something.SimpleAccountService">
<!-- insert dependencies as required here -->
</bean>
<!-- in the child (descendant) context -->
<bean id="accountService" <!-- bean name is the same as the parent bean -->
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref parent="accountService"/> <!-- notice how we refer to the parent bean -->
</property>
<!-- insert other configuration and dependencies as required here -->
</bean>
ref エレメントの local 属性は、通常の bean 参照を超える値を提供しないため、4.0 Bean XSD ではサポートされなくなりました。4.0 スキーマにアップグレードするときに、既存の ref local 参照を ref bean に変更します。 |
インナー bean
<property/>
または <constructor-arg/>
要素内の <bean/>
要素は、次の例に示すように、内部 Bean を定義します。
<bean id="outer" class="...">
<!-- instead of using a reference to a target bean, simply define the target bean inline -->
<property name="target">
<bean class="com.example.Person"> <!-- this is the inner bean -->
<property name="name" value="Fiona Apple"/>
<property name="age" value="25"/>
</bean>
</property>
</bean>
内部 Bean 定義には、定義済みの ID または名前は必要ありません。指定されている場合、コンテナーはそのような値を識別子として使用しません。コンテナーは、作成時に scope
フラグも無視します。これは、内部 Bean は常に匿名であり、常に外部 Bean で作成されるためです。インナー Bean に独立してアクセスしたり、内包する Bean 以外のコラボレーション Bean に注入したりすることはできません。
コーナーケースとして、たとえばシングルトン Bean に含まれるリクエストスコープの内部 Bean の場合、カスタムスコープから破棄コールバックを受け取ることができます。内側の Bean インスタンスの作成は、含まれる Bean に関連付けられていますが、破棄コールバックにより、リクエストスコープのライフサイクルに参加できます。これは一般的なシナリオではありません。通常、内部 Bean は、含まれる Bean のスコープを単に共有します。
コレクション
<list/>
、<set/>
、<map/>
、<props/>
要素は、Java Collection
型 List
、Set
、Map
、Properties
のプロパティと引数をそれぞれ設定します。次の例は、それらの使用方法を示しています。
<bean id="moreComplexObject" class="example.ComplexObject">
<!-- results in a setAdminEmails(java.util.Properties) call -->
<property name="adminEmails">
<props>
<prop key="administrator">[email protected] (英語) </prop>
<prop key="support">[email protected] (英語) </prop>
<prop key="development">[email protected] (英語) </prop>
</props>
</property>
<!-- results in a setSomeList(java.util.List) call -->
<property name="someList">
<list>
<value>a list element followed by a reference</value>
<ref bean="myDataSource" />
</list>
</property>
<!-- results in a setSomeMap(java.util.Map) call -->
<property name="someMap">
<map>
<entry key="an entry" value="just some string"/>
<entry key="a ref" value-ref="myDataSource"/>
</map>
</property>
<!-- results in a setSomeSet(java.util.Set) call -->
<property name="someSet">
<set>
<value>just some string</value>
<ref bean="myDataSource" />
</set>
</property>
</bean>
マップキーまたは値の値、または設定値は、次の要素のいずれかです。
bean | ref | idref | list | set | map | props | value | null
コレクションのマージ
Spring コンテナーは、コレクションのマージもサポートしています。アプリケーション開発者は、親 <list/>
、<map/>
、<set/>
または <props/>
要素を定義し、子 <list/>
、<map/>
、<set/>
または <props/>
要素が親コレクションから値を継承およびオーバーライドするようにできます。つまり、子コレクションの値は、親コレクションと子コレクションの要素をマージした結果であり、子コレクションの要素は親コレクションで指定された値をオーバーライドします。
マージに関するこのセクションでは、親子 Bean のメカニズムについて説明します。親 Bean と子 Bean 定義を持つリーダー未知 は、続行する前に関連するセクションを読むことをお勧めします。
次の例は、コレクションのマージを示しています。
<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">
<!-- the merge is specified on the child collection definition -->
<props merge="true">
<prop key="sales">[email protected] (英語) </prop>
<prop key="support">[email protected] (英語) </prop>
</props>
</property>
</bean>
<beans>
child
Bean 定義の adminEmails
プロパティの <props/>
要素で merge=true
属性が使用されていることに注意してください。child
Bean がコンテナーによって解決およびインスタンス化されると、結果のインスタンスには、子の adminEmails
コレクションを親の adminEmails
コレクションとマージした結果を含む adminEmails
Properties
コレクションが含まれます。次のリストは結果を示しています。
子 Properties
コレクションの値セットは親 <props/>
からすべてのプロパティ要素を継承し、support
値の子の値は親コレクションの値をオーバーライドします。
このマージ動作は、<list/>
、<map/>
、<set/>
コレクション型と同様に適用されます。<list/>
エレメントの特定のケースでは、List
コレクション・型に関連付けられたセマンティクス(つまり、ordered
値のコレクションの概念)が維持されます。親の値は、子リストのすべての値の前にあります。Map
、Set
、Properties
コレクション型の場合、順序はありません。コンテナーが内部で使用する関連する Map
、Set
、Properties
実装型の基礎となるコレクション・型には、順序付けのセマンティクスは有効ではありません。
コレクションのマージの制限
異なるコレクション型(Map
と List
など)をマージすることはできません。そうしようとすると、適切な Exception
がスローされます。merge
属性は、下位の継承された子定義で指定する必要があります。親コレクション定義で merge
属性を指定することは冗長であり、目的のマージにはなりません。
強く型付けされたコレクション
ジェネリクス型に対する Java のサポートのおかげで、強く型付けされたコレクションを使用できます。つまり、(たとえば) String
要素のみを含むことができるように Collection
型を宣言することができます。Spring を使用して強い型の Collection
を Bean に依存性注入する場合は、Spring の型変換サポートを利用して、強い型の Collection
インスタンスの要素を適切な型に変換してからに追加することができます。Collection
。次の Java クラスと Bean 定義は、その方法を示しています。
Java
Kotlin
public class SomeClass {
private Map<String, Float> accounts;
public void setAccounts(Map<String, Float> accounts) {
this.accounts = accounts;
}
}
class SomeClass {
lateinit var accounts: Map<String, Float>
}
<beans>
<bean id="something" class="x.y.SomeClass">
<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>
something
Bean の accounts
プロパティが注入用に準備されると、強く型付けされた Map<String, Float>
の要素型に関する一般的な情報がリフレクションによって利用可能になります。Spring の型変換インフラストラクチャは、さまざまな値要素を Float
型として認識し、文字列値(9.99
、2.75
、3.99
)が実際の Float
型に変換されます。
NULL および空の文字列値
Spring は、プロパティなどの空の引数を空の Strings
として扱います。次の XML ベースの構成メタデータスニペットは、email
プロパティを空の String
値("")に設定します。
<bean class="ExampleBean">
<property name="email" value=""/>
</bean>
上記の例は、次の Java コードと同等です。
Java
Kotlin
exampleBean.setEmail("");
exampleBean.email = ""
<null/>
要素は null
値を処理します。次のリストに例を示します。
<bean class="ExampleBean">
<property name="email">
<null/>
</property>
</bean>
上記の構成は、次の Java コードと同等です。
Java
Kotlin
exampleBean.setEmail(null);
exampleBean.email = null
p-namespace を使用した XML ショートカット
p- 名前空間では、ネストされた <property/>
要素の代わりに bean
要素の属性を使用して、プロパティ値をコラボレーションする Bean、またはその両方を記述することができます。
Spring は、XML スキーマ定義に基づく、名前空間を使用した拡張可能な構成形式をサポートします。この章で説明する beans
構成形式は、XML スキーマドキュメントで定義されます。ただし、p 名前空間は XSD ファイル内で定義されておらず、Spring のコア内にのみ存在します。
次の例は、同じ結果に解決される 2 つの XML スニペット(1 つ目は標準 XML 形式を使用し、2 つ目は p-namespace を使用)を示しています。
<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
https://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>
この例は、Bean 定義の email
と呼ばれる p 名前空間の属性を示しています。これは、Spring にプロパティ宣言を含めるように指示します。前述したように、p-namespace にはスキーマ定義がないため、属性の名前をプロパティ名に設定できます。
次の例には、さらに 2 つの Bean 定義が含まれており、両方とも別の Bean への参照を持っています。
<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
https://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-namespace を使用したプロパティ値だけでなく、プロパティ参照を宣言するための特別な形式も含まれています。最初の Bean 定義では <property name="spouse" ref="jane"/>
を使用して Bean john
から Bean jane
への参照を作成しますが、2 番目の Bean 定義では p:spouse-ref="jane"
を属性として使用してまったく同じことを行います。この場合、spouse
はプロパティ名ですが、-ref
部分は、これがストレート値ではなく、別の Bean への参照であることを示しています。
p-namespace は、標準の XML 形式ほど柔軟ではありません。例: プロパティ参照を宣言する形式は、Ref で終わるプロパティと衝突しますが、標準の XML 形式は衝突しません。3 つのアプローチすべてを同時に使用する XML ドキュメントを作成しないように、アプローチを慎重に選択し、チームメンバーに伝えることをお勧めします。 |
c-namespace を使用した XML ショートカット
p-namespace を使用した XML ショートカットと同様に、Spring 3.1 で導入された c-namespace では、ネストされた constructor-arg
要素ではなく、コンストラクター引数を構成するためのインライン属性を使用できます。
次の例では、c:
名前空間を使用して、コンストラクターベースの依存性注入からと同じことを行います。
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="beanTwo" class="x.y.ThingTwo"/>
<bean id="beanThree" class="x.y.ThingThree"/>
<!-- traditional declaration with optional argument names -->
<bean id="beanOne" class="x.y.ThingOne">
<constructor-arg name="thingTwo" ref="beanTwo"/>
<constructor-arg name="thingThree" ref="beanThree"/>
<constructor-arg name="email" value="[email protected] (英語) "/>
</bean>
<!-- c-namespace declaration with argument names -->
<bean id="beanOne" class="x.y.ThingOne" c:thingTwo-ref="beanTwo"
c:thingThree-ref="beanThree" c:email="[email protected] (英語) "/>
</beans>
c:
名前空間は、名前でコンストラクター引数を設定するために、p:
の名前空間(Bean 参照の末尾の -ref
)と同じ規則を使用します。同様に、XSD スキーマ(Spring コア内に存在する)で定義されていない場合でも、XML ファイルで宣言する必要があります。
コンストラクター引数名が使用できないまれなケース (通常、バイトコードが -parameters
フラグなしでコンパイルされた場合) では、次のように引数インデックスにフォールバックできます。
<!-- c-namespace index declaration -->
<bean id="beanOne" class="x.y.ThingOne" c:_0-ref="beanTwo" c:_1-ref="beanThree"
c:_2="[email protected] (英語) "/>
XML 文法により、XML 属性名は数字で始めることができないため(インデックスの表記法では先頭の _ の存在が必要です(一部の IDE では許可されていますが)。対応するインデックス表記は <constructor-arg> 要素にも使用できますが、通常は宣言の単純な順序で十分なので一般的には使用されません。 |
実際には、コンストラクター解決メカニズムは引数の照合に非常に効率的であるため、本当に必要な場合を除いて、構成全体で名前表記を使用することをお勧めします。
複合プロパティ名
最終プロパティ名を除くパスのすべてのコンポーネントが null
でない限り、Bean プロパティを設定するときに複合またはネストされたプロパティ名を使用できます。以下の Bean 定義を考慮してください。
<bean id="something" class="things.ThingOne">
<property name="fred.bob.sammy" value="123" />
</bean>
something
Bean には fred
プロパティがあり、bob
プロパティには sammy
プロパティがあり、その最終 sammy
プロパティには 123
の値が設定されています。これが機能するためには、Bean の作成後に something
の fred
プロパティと fred
の bob
プロパティが null
であってはなりません。そうでない場合、NullPointerException
がスローされます。