Spring FactoryBeanの使い方は?

Spring FactoryBeanの使用方法

1. 概要

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

そして、簡単に言えば、org.springframework.beans.factory.FactoryBeanインターフェースを実装することでファクトリー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 {

    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



    
        
        
    

次に、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));
    }
}

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

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

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

FactoryBeanにアクセスするには、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. Javaベースの構成でFactoryBeanを使用する

Javaベースの構成でFactoryBeanを使用することは、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つのソリューションの使用に関する詳細は、別の記事Guide To Running Logic on Startup in Springで紹介されています。

4. AbstractFactoryBean

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

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

public class SingleToolFactory extends AbstractFactoryBean {

    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 {

    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設定:



    
        
        
    

    
        
        
    

これで、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の初期化。

いつものように、完全なソースはover on GitHubです。