開発者ドキュメント

春のコンストラクタ注入型のあいまいさ

Springフレームワークでは、同じ数の引数を持つ複数のコンストラクタがクラスに含まれていると、常にコンストラクタ注入引数型のあいまいさ** 問題が発生します。

問題

この顧客ビーンの例を見てみましょう。これは2つのコンストラクターメソッドを含み、どちらも3つの引数を異なるデータ型で受け入れます。

package com.mkyong.common;

public class Customer
{
    private String name;
    private String address;
    private int age;

    public Customer(String name, String address, int age) {
        this.name = name;
        this.address = address;
        this.age = age;
    }

    public Customer(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
   //getter and setter methods
    public String toString(){
        return " name : " +name + "\n address : "
               + address + "\n age : " + age;
    }

}

Spring bean設定ファイルでは、名前に ‘mkyong’、アドレスに ‘188’、年齢に ’28’を渡します。

<!--Spring-Customer.xml-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="CustomerBean" class="com.mkyong.common.Customer">

        <constructor-arg>
            <value>mkyong</value>
        </constructor-arg>

        <constructor-arg>
            <value>188</value>
        </constructor-arg>

        <constructor-arg>
            <value>28</value>
        </constructor-arg>
        </bean>

</beans>

それを実行する、あなたの期待された結果は何ですか?

package com.mkyong.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App
{
    public static void main( String[]args )
    {
        ApplicationContext context =
          new ClassPathXmlApplicationContext(new String[]{"Spring-Customer.xml"});

        Customer cust = (Customer)context.getBean("CustomerBean");
        System.out.println(cust);
    }
}

出力

 name : mkyong
 address : 28
 age : 188

結果は、最初のコンストラクタではなく、2番目のコンストラクタが実行されたときに期待した結果とは異なります。 Springでは、引数型 ‘188’はintに変換できるので、Springはそれを変換して2番目のコンストラクタを取ります。

また、Springが使用するコンストラクタを解決できない場合、次のエラーメッセージが表示されます

constructor arguments specified but no matching constructor
found in bean 'CustomerBean' (hint: specify index and/or
type arguments for simple parameters to avoid type ambiguities)

解決策

これを修正するには、コンストラクタの正確なデータ型を常に以下のようなtype属性で指定する必要があります。

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="CustomerBean" class="com.mkyong.common.Customer">

        <constructor-arg type="java.lang.String">
            <value>mkyong</value>
        </constructor-arg>

        <constructor-arg type="java.lang.String">
            <value>188</value>
        </constructor-arg>

        <constructor-arg type="int">
            <value>28</value>
        </constructor-arg>

    </bean>

</beans>

もう一度実行して、あなたが期待したものを手に入れましょう。

出力
 name : mkyong
 address : 188
 age : 28
モバイルバージョンを終了