34

FactoryBean使用して、複雑なインスタンス化ロジックを必要とする可能性のあるオブジェクトをプログラムで作成できます。

しかし、によって作成された豆FactoryBeanは春の管理にはならないようです。この解釈は正しいですか?もしそうなら、何か良い回避策はありますか?私の問題を説明するために、短いコードサンプルが含まれています。

ApplicationContext:

<bean id="searcher" class="some.package.SearcherFactory" /> 
<bean id="service" class="some.package.Service" /> 

工場での実装:

public class SearcherFactory implements FactoryBean<Searcher> {

    @Override
    public Searcher getObject() throws Exception {
        return new Searcher(); // not so complex after all ;)
    }

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

工場で作成されたクラス:

public class Searcher() {
      private Service service;

      @Autowired
      public void setService(Service service) {
           // never invoked
           this.service=service;
      } 
}
4

5 に答える 5

33

自動配線を行う抽象的なFactoryBean実装は次のとおりです。

public abstract class AbstractAutowiringFactoryBean<T> extends
    AbstractFactoryBean<T> implements ApplicationContextAware{

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(
        final ApplicationContext applicationContext){
        this.applicationContext = applicationContext;
    }

    @Override
    protected final T createInstance() throws Exception{
        final T instance = doCreateInstance();
        if(instance != null){
            applicationContext
              .getAutowireCapableBeanFactory()
              .autowireBean(instance);
        }
        return instance;
    }

    /**
     * Create the bean instance.
     * 
     * @see #createInstance()
     */
    protected abstract T doCreateInstance();

}

それを拡張し、メソッドgetObjectType()doCreateInstance()メソッドを実装すると、自動配線が可能になります。

注: BeanPostProcessorsは適用されないため、追加のコードが必要になります。

于 2011-02-11T15:54:15.760 に答える
23

によって作成されたオブジェクトはSpringFactoryBean によって管理されますが、Springによってインスタンス化または構成されません。を使用することによりFactoryBean、あなたはそれに対して自分で責任を負います。すべてのインジェクションと設定は、FactoryBean

あなたにとってよりうまくいくかもしれない代替案があります-XMLベースの設定の代わりに注釈ベースの設定を使用してください。@Autowiredこれは、オブジェクト自体のようなものを使用しながら、Javaで複雑なインスタンス化ロジックを使用できることを意味します。

私は今、すべての重要なSpringアプリにアノテーションスタイルの構成を使用する傾向があります。これにより、多くのことがはるかに簡単になります。

于 2011-02-11T15:30:18.740 に答える
18

これはどうですか ?

<bean id="serviceFactory"
      class="some.package.SearcherFactory" />


<bean id="service"
      factory-bean="serviceFactory"
      factory-method="getObject"/>

...次に、Beanの「サービス」を注入するだけで、コード内のファクトリを気にする必要はありません。

于 2011-02-11T16:18:28.827 に答える
4

手動の方法は次のようになります。

  1. ファクトリBeanに依存関係を注入します
  2. ターゲットオブジェクトに手動で設定します。

ApplicationContextファクトリBeanに注入する(または実装して取得するApplicationContextAware)こともできます。ctx.getAutowireCapableBeanFactory().autowireBean(bean)

しかし、私は両方とも奇妙に感じることを認めます。

ただし、実際には、ロジックが非常に単純な場合(インスタンス化のみ)、prototypeスコープを使用します。

于 2011-02-11T14:50:58.463 に答える
0

FactoryBeanは、開発者がファクトリクラスを作成するときに実装するインターフェイスであり、ファクトリクラスによって作成されたオブジェクトをSpringによってBeanとして管理する必要があります。一方、BeanFactoryはSpringIoCコンテナを表します。管理対象Beanが含まれ、それらを取得するためのアクセスを提供します。これは、制御の反転の基本機能を実装するフレームワークのコアの一部です。

フレームワークのコア機能を拡張しない限り、ほとんどの場合、BeanFactoryインターフェースを直接使用または実装することはありません。ただし、Springで管理する必要のあるファクトリによって作成されたオブジェクトがある場合は、FactoryBeanを実装します。

より簡潔に言えば、BeanFactoryはSpringコンテナを表し、FactoryBeanは、作成されたオブジェクトがピックアップされてコンテナ内のBeanとして登録されるファクトリクラスを表します。

File: context.xml

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">

    <bean id="sha" class="MessageDigestFactoryBean">
        <property name="algorithm" value="SHA1"/>
    </bean>

    <bean id="md5" class="MessageDigestFactoryBean"/>

</beans>


File: Main.java

import java.security.MessageDigest;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class Main {
  public static void main(String[] args) {
    XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("context.xml"));
    String d1 = (String) factory.getBean("sha");
    String d2 = (String) factory.getBean("md5");
    System.out.println(d1);
    System.out.println(d2);
  }

}

class MessageDigestFactoryBean implements FactoryBean, InitializingBean {
  private static final String DEFAULT_ALGORITHM = "MD5";

  private String algorithm = DEFAULT_ALGORITHM;

  public Object getObject() throws Exception {
    return this.algorithm;
  }

  public Class getObjectType() {
    return MessageDigest.class;
  }

  public boolean isSingleton() {
    return true;
  }

  public void setAlgorithm(String algorithm) {
    this.algorithm = algorithm;
  }

  public void afterPropertiesSet() throws Exception {
    this.algorithm += " after setting";
  }
}
于 2016-04-19T18:15:33.600 に答える