1. 概要

Spring beanコンテナには、通常のbeanとファクトリbeanの2種類のbeanがあります。 Springは前者を直接使用しますが、後者はフレームワークによって管理されるオブジェクト自体を生成できます。

そして、簡単に言えば、org.springframework。beans.factory.Factory Bean インターフェースを実装することで、ファクトリbeanを構築できます。

2. ファクトリービーンズの基本

2.1. FactoryBeanを実装します

最初にFactoryBeanインターフェースを見てみましょう。

public interface FactoryBean {
    T getObject() throws Exception;
    Class<?> getObjectType();
    boolean isSingleton();
}

3つの方法について説明しましょう。

  • getObject() –ファクトリによって生成されたオブジェクトを返します。これは、Springコンテナによって使用されるオブジェクトです。
  • getObjectType() –このFactoryBeanが生成するオブジェクトのタイプを返します
  • isSingleton() –このFactoryBeanによって生成されたオブジェクトがシングルトンであるかどうかを示します

それでは、例FactoryBeanを実装しましょう。 タイプToolのオブジェクトを生成するToolFactoryを実装します。

public class Tool {

    private int id;

    // standard constructors, getters and setters
}

ToolFactory 自体:

public class ToolFactory implements FactoryBean<Tool> {

    private int factoryId;
    private int toolId;

    @Override
    public Tool getObject() throws Exception {
        return new Tool(toolId);
    }

    @Override
    public Class<?> getObjectType() {
        return Tool.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

    // standard setters and getters
}

ご覧のとおり、ToolFactoryFactoryBeanであり、Toolオブジェクトを生成できます。

2.2. XMLベースの構成でFactoryBeanを使用する

ToolFactoryの使用方法を見てみましょう。

XMLベースの構成でツールの構築を開始します– factorybean- spring -ctx.xml

<beans ...>

    <bean id="tool" class="com.baeldung.factorybean.ToolFactory">
        <property name="factoryId" value="9090"/>
        <property name="toolId" value="1"/>
    </bean>
</beans>

次に、Toolオブジェクトが正しく挿入されているかどうかをテストできます。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:factorybean-spring-ctx.xml" })
public class FactoryBeanXmlConfigTest {
    @Autowired
    private Tool tool;

    @Test
    public void testConstructWorkerByXml() {
        assertThat(tool.getId(), equalTo(1));
    }
}

テスト結果は、 ToolFactory によって生成されたツールオブジェクトに、 factorybean- spring-ctx.xmlで構成したプロパティを注入できることを示しています。

テスト結果は、Springコンテナーが、依存性注入のためにそれ自体ではなく、FactoryBeanによって生成されたオブジェクトを使用することも示しています。

SpringコンテナはFactoryBeangetObject()メソッドの戻り値をbeanとして使用しますが、FactoryBeanを使用することもできます。 自体。

アクセスするには工場Bean 、bean名の前に「&」を追加するだけです。

ファクトリbeanとそのfactoryIdプロパティを取得してみましょう。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:factorybean-spring-ctx.xml" })
public class FactoryBeanXmlConfigTest {

    @Resource(name = "&tool")
    private ToolFactory toolFactory;

    @Test
    public void testConstructWorkerByXml() {
        assertThat(toolFactory.getFactoryId(), equalTo(9090));
    }
}

2.3. FactoryBeanをJavaベースの構成で使用する

FactoryBean をJavaベースの構成で使用することは、XMLベースの構成とは少し異なります。 FactoryBeangetObject()メソッドを明示的に呼び出す必要があります。 。

前のサブセクションの例をJavaベースの構成例に変換してみましょう。

@Configuration
public class FactoryBeanAppConfig {
 
    @Bean(name = "tool")
    public ToolFactory toolFactory() {
        ToolFactory factory = new ToolFactory();
        factory.setFactoryId(7070);
        factory.setToolId(2);
        return factory;
    }

    @Bean
    public Tool tool() throws Exception {
        return toolFactory().getObject();
    }
}

次に、Toolオブジェクトが正しく挿入されているかどうかをテストします。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = FactoryBeanAppConfig.class)
public class FactoryBeanJavaConfigTest {

    @Autowired
    private Tool tool;
 
    @Resource(name = "&tool")
    private ToolFactory toolFactory;

    @Test
    public void testConstructWorkerByJava() {
        assertThat(tool.getId(), equalTo(2));
        assertThat(toolFactory.getFactoryId(), equalTo(7070));
    }
}

テスト結果は、以前のXMLベースの構成テストと同様の効果を示しています。

3. 初期化する方法

FactoryBean が設定された後、プロパティチェックのように、 getObject()メソッドが呼び出される前にいくつかの操作を実行する必要がある場合があります。

これを実現するには、 InitializingBean インターフェースを実装するか、@PostConstructアノテーションを使用します。

これら2つのソリューションの使用に関する詳細は、別の記事で紹介されています:Springでの起動時にロジックを実行するためのガイド。

4. AbstractFactoryBean

Springは、FactoryBean実装用の単純なテンプレートスーパークラスとしてAbstractFactoryBeanを提供します。 この基本クラスを使用すると、シングルトンまたはプロトタイプオブジェクトを作成するファクトリbeanをより便利に実装できるようになります。

SingleToolFactoryNonSingleToolFactoryを実装して、シングルトンタイプとプロトタイプタイプの両方でAbstractFactoryBeanを使用する方法を示しましょう。

public class SingleToolFactory extends AbstractFactoryBean<Tool> {

    private int factoryId;
    private int toolId;

    @Override
    public Class<?> getObjectType() {
        return Tool.class;
    }

    @Override
    protected Tool createInstance() throws Exception {
        return new Tool(toolId);
    }

    // standard setters and getters
}

そして今、非シングルトンの実装:

public class NonSingleToolFactory extends AbstractFactoryBean<Tool> {

    private int factoryId;
    private int toolId;

    public NonSingleToolFactory() {
        setSingleton(false);
    }

    @Override
    public Class<?> getObjectType() {
        return Tool.class;
    }

    @Override
    protected Tool createInstance() throws Exception {
        return new Tool(toolId);
    }

    // standard setters and getters
}

また、これらのファクトリBeanのXML構成は次のとおりです。

<beans ...>

    <bean id="singleTool" class="com.baeldung.factorybean.SingleToolFactory">
        <property name="factoryId" value="3001"/>
        <property name="toolId" value="1"/>
    </bean>

    <bean id="nonSingleTool" class="com.baeldung.factorybean.NonSingleToolFactory">
        <property name="factoryId" value="3002"/>
        <property name="toolId" value="2"/>
    </bean>
</beans>

これで、Workerオブジェクトのプロパティが期待どおりに挿入されているかどうかをテストできます。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:factorybean-abstract-spring-ctx.xml" })
public class AbstractFactoryBeanTest {

    @Resource(name = "singleTool")
    private Tool tool1;
 
    @Resource(name = "singleTool")
    private Tool tool2;
 
    @Resource(name = "nonSingleTool")
    private Tool tool3;
 
    @Resource(name = "nonSingleTool")
    private Tool tool4;

    @Test
    public void testSingleToolFactory() {
        assertThat(tool1.getId(), equalTo(1));
        assertTrue(tool1 == tool2);
    }

    @Test
    public void testNonSingleToolFactory() {
        assertThat(tool3.getId(), equalTo(2));
        assertThat(tool4.getId(), equalTo(2));
        assertTrue(tool3 != tool4);
    }
}

テストからわかるように、 SingleToolFactory はシングルトンオブジェクトを生成し、NonSingleToolFactoryはプロトタイプオブジェクトを生成します。

AbstractFactory では、シングルトンプロパティのデフォルト値は true であるため、SingleToolFactoryでシングルトンプロパティを設定する必要はありません。

5. 結論

FactoryBean を使用すると、複雑な構築ロジックをカプセル化したり、Springで高度に構成可能なオブジェクトを簡単に構成したりすることができます。

そのため、この記事では、 FactoryBean の実装方法の基本、XMLベースの構成とJavaベースの構成の両方での使用方法、およびFactoryBeanのその他のさまざまな側面を紹介しました。 FactoryBeanおよびAbstractFactoryBeanの初期化などの

いつものように、完全なソースはGitHubにあります。