1. 序章

ファクトリメソッドは、単一のメソッド呼び出し内に複雑な作成ロジックを隠すための便利な手法です。

通常、Springではコンストラクターまたはフィールドインジェクションを使用してBeanを作成しますが、ファクトリメソッドを使用してSpringBeanを作成することもできます。

このチュートリアルでは、インスタンスメソッドと静的ファクトリメソッドの両方を使用してSpringBeanを作成する方法について詳しく説明します。

2. インスタンスファクトリメソッド

ファクトリメソッドパターンの標準的な実装は、目的のBeanを返すインスタンスメソッドを作成することです。

さらに、引数の有無にかかわらず目的のBeanを作成するようにSpringを構成できます

2.1. 引数なし

作成中のBeanを表すFooクラスを作成できます。

public class Foo {}

次に、 Foobeanを作成するファクトリメソッドcreateInstanceを含むInstanceFooFactoryクラスを作成します。

public class InstanceFooFactory {

    public Foo createInstance() {
        return new Foo();
    }
}

その後、Springを構成します。

  1. ファクトリクラスのBeanを作成します( InstanceFooFactory
  2. factory-bean 属性を使用して、ファクトリBeanを参照します
  3. factory-method 属性を使用して、ファクトリメソッドを参照します( createInstance

これをSpringXML構成に適用すると、次のようになります。

<beans ...>

    <bean id="instanceFooFactory"
      class="com.baeldung.factorymethod.InstanceFooFactory" />

    <bean id="foo"
      factory-bean="instanceFooFactory"
      factory-method="createInstance" />

</beans>

最後に、目的のFooBeanを自動配線します。 次に、SpringはcreateInstanceファクトリメソッドを使用してBeanを作成します。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/factorymethod/instance-config.xml")
public class InstanceFooFactoryIntegrationTest {

    @Autowired
    private Foo foo;
    
    @Test
    public void givenValidInstanceFactoryConfig_whenCreateFooInstance_thenInstanceIsNotNull() {
        assertNotNull(foo);
    }
}

2.2. 引数付き

Spring構成のconstructor-argelementを使用して、インスタンスファクトリメソッドに引数を提供することもできます。

まず、引数を利用するクラスBarを作成します。

public class Bar {

    private String name;

    public Bar(String name) {
        this.name = name;
    }

    // ...getters & setters
}

次に、引数を受け入れて Bar Beanを返すファクトリメソッドを使用して、インスタンスファクトリクラスInstanceBarFactoryを作成します。

public class InstanceBarFactory {

    public Bar createInstance(String name) {
        return new Bar(name);
    }
}

最後に、コンストラクタ-arg要素をBarBean定義に追加します。

<beans ...>

    <bean id="instanceBarFactory"
      class="com.baeldung.factorymethod.InstanceBarFactory" />

    <bean id="bar"
      factory-bean="instanceBarFactory"
      factory-method="createInstance">
        <constructor-arg value="someName" />
    </bean>

</beans>

次に、 Foo Beanの場合と同じ方法で、BarBeanを自動配線できます。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/factorymethod/instance-bar-config.xml")
public class InstanceBarFactoryIntegrationTest {

    @Autowired
    private Bar instance;
    
    @Test
    public void givenValidInstanceFactoryConfig_whenCreateInstance_thenNameIsCorrect() {
        assertNotNull(instance);
        assertEquals("someName", instance.getName());
    }
}

3. 静的ファクトリメソッド

静的メソッドをファクトリメソッドとして使用するようにSpringを構成することもできます。

インスタンスファクトリメソッドを優先する必要がありますが、この手法は、目的のBeanを生成する既存のレガシー静的メソッドがある場合に役立ちます。たとえば、ファクトリメソッドがシングルトンを返す場合、これを使用するようにSpringを構成できます。シングルトンファクトリメソッド。

インスタンスファクトリメソッドと同様に、引数の有無にかかわらず静的メソッドを構成できます。

3.1. 引数なし

Foo クラスを目的のBeanとして使用して、のシングルトンインスタンスを返すcreateInstanceファクトリメソッドを含むクラスSingletonFooFactoryを作成できます。 Foo

public class SingletonFooFactory {

    private static final Foo INSTANCE = new Foo();
    
    public static Foo createInstance() {
        return INSTANCE;
    }
}

今回は、1つのBeanを作成するだけで済みます。このBeanに必要な属性は次の2つだけです。

  1. class –ファクトリクラスを宣言します( SingletonFooFactory
  2. factory-method –静的ファクトリメソッドを宣言します( createInstance

これをSpringXML構成に適用すると、次のようになります。

<beans ...>

    <bean id="foo"
      class="com.baeldung.factorymethod.SingletonFooFactory"
      factory-method="createInstance" />

</beans>

最後に、以前と同じ構造を使用してFooBeanを自動配線します。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/factorymethod/static-foo-config.xml")
public class SingletonFooFactoryIntegrationTest {

    @Autowired
    private Foo singleton;
    
    @Test
    public void givenValidStaticFactoryConfig_whenCreateInstance_thenInstanceIsNotNull() {
        assertNotNull(singleton);
    }
}

3.2. 引数付き

可能な場合は、静的オブジェクト(シングルトンなど)の状態を変更しないようにする必要がありますが、静的ファクトリメソッドに引数を渡すことはできます。

これを行うには、必要な引数を受け入れる新しいファクトリメソッドを作成します。

public class SingletonBarFactory {

    private static final Bar INSTANCE = new Bar("unnamed");
    
    public static Bar createInstance(String name) {
        INSTANCE.setName(name);
        return INSTANCE;
    }
}

その後、コンストラクター引数要素を使用して目的の引数を渡すようにSpringを構成します。

<beans ...>

    <bean id="bar"
      class="com.baeldung.factorymethod.SingletonBarFactory"
      factory-method="createInstance">
        <constructor-arg value="someName" />
    </bean>

</beans>

最後に、以前と同じ構造を使用してBarBeanを自動配線します。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/factorymethod/static-bar-config.xml")
public class SingletonBarFactoryIntegrationTest {

    @Autowired
    private Bar instance;
    
    @Test
    public void givenValidStaticFactoryConfig_whenCreateInstance_thenNameIsCorrect() {
        assertNotNull(instance);
        assertEquals("someName", instance.getName());
    }
}

4. 結論

この記事では、引数の有無にかかわらず、インスタンスメソッドと静的ファクトリメソッドを使用するようにSpringを構成する方法について説明しました。

コンストラクターとフィールドインジェクションを使用してBeanを作成するのが一般的ですが、ファクトリメソッドは複雑な作成手順やレガシーコードに便利です。

この記事で使用されているコードは、GitHubにあります。