1

プロパティ ファイルの値に基づいて DAO の実装を切り替えられるようにしたいアプリケーションがあります。Spring FactoryBean インターフェースは、プロパティ値に基づいて切り替える作業を内部で実行できる FactoryBean を介して DAO を提供できるという点でうまく機能するように見えます。

ただし、このspringsource ブログ投稿の最後の段落では、次の警告について言及しています。

ここでの重要なポイントの 1 つは、ファクトリ化されたオブジェクト自体ではなく、Spring コンテナーに存在し、ライフサイクル フックとコンテナー サービスを享受するのは FactoryBean であるということです。返されたインスタンスは一時的です。Spring は、 getObject() から返されたものについて何も認識せず、ライフサイクル フックやその他のものを実行しようとしません。

私の DAO オブジェクトには、Spring アノテーション@Repository@Transactional. 上記の段落に照らして、FactoryBean を介して DAO 実装を返す場合、これらの注釈は無視されますか? もしそうなら、Spring が FactoryBean によって返された Bean を管理していることを確認する良い方法は何ですか?

編集:ほとんどの人が問題に対する代替構成ソリューションを提供しているようです。私はこれらの提案を受け入れていますが (そして、それらが良い場合は賛成します)、私の質問は実際には適切な FactoryBean の使用法に関係しており、それらの質問に基づいて正しい回答をマークします。

4

4 に答える 4

4

次のようなものがあるとします。

public interface FooDao {
   // ...
}

@Repository("firstFooDao")
public class FirstFooDao  implements FooDao {
   //...
}

@Repository("secondFooDao")
public class SecondFooDao  implements FooDao {
   //...
}

fooプレースホルダー (この例では)に基づいて適切な実装を返す構成クラスを作成できます。

@Configuration
public class FooDaoConfiguration {

    @Value("${foo}")
    private String foo;

    @Autowired
    private BeanFactory beanFactory;

    @Bean
    @Primary
    public FooDao fooDao() {
        return beanFactory.getBean(foo, FooDao.class);
    }

}

次に、プロパティ ファイルで実装を切り替えることができます。

#foo=firstFooDao
foo=secondFooDao

このように、両方の実装はスプリングによって管理されます。リンクされたドキュメントの例とは異なり、返されたオブジェクトはスプリング以外のファクトリを使用して構築されます。この場合、すべての Bean は春によってインスタンス化されます。構成クラスは 1 つを選択します。

于 2013-05-08T08:41:37.787 に答える
1

Beanの属性でプロパティ プレースホルダーを使用できるためclass、適切な命名規則があれば、次のようなものを使用できます。

<bean id="customerDao" class="com.example.dao.${dao.type}.CustomerDao">

ファクトリ Bean を使用する代わりに。

于 2013-05-07T20:02:26.927 に答える
0

@Component または XML を使用して、通常どおり Spring コンテキストで DAO インスタンス宣言を作成します。それらがすべて共通のインターフェースを継承すると仮定すると、後でリストを使用してそれらをすべて収集できます。この型収集メカニズムの詳細については、次のリンクを参照してください: http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-autowired-annotation

たとえば、DAOFactory では次のようになります。

@Component
class MyCarDAOFactory implements ApplicationContextAware,FactoryBean<CarDAO> {

// Getters and Setters for the ApplicationContextAware interface..
ApplicationContext ctx;
// ...

  // This will place any class that implements CarDAO from Spring Context.
  @Inject
  List<CarDAO> carDaoEntries;

  // This method returns a CarDAO as classified by its Name property specified in 
  // a property placeholder value ( should it have been set in Spring context 
  // via a PropertyPlaceholder)
  public CarDAO getObject() {
   final String val = ctx.getEnvironment().getProperty("MY_PROPERTY_KEY");
      return CollectionUtils.find(carDaoEntries, new Predicate() {

        public boolean evaluate(Object object) {
            return ((CarDAO) object).getName().startsWith(val);
        }
    });
  }
}

さて、この種の問題に対するよりエレガントでシンプルな解決策があるかもしれません。

于 2013-05-08T06:28:15.963 に答える