2012-02-29 7 views
2

別のプロジェクトでGrails内で行う最良の方法がわからないという状況に遭遇しました。これを設定するには、これがプレーンなSpringプロジェクトでやっていることです。共有インターフェースから継承した複数のSpring Beanをサービス内の配列に挿入する

私は2つの同じインタフェースから継承するクラスがあります。

public interface BaseInterface { 
    void doSomething(); 
} 

public class Impl1 implements BaseInterface { 
    public void doSomething(){ 
     System.out.println("doing impl 1"); 
    } 
} 

public class Impl2 implements BaseInterface { 
    public void doSomething(){ 
     System.out.println("doing impl 2"); 
    } 
} 

これまでのところ、かなりの標準を、私は私が仕事をするために順番に呼び出したいN豆を持っています。 (この例は明らかに自明である)。別のJavaクラスでは、配列として注入されたすべてのBean(autowired)を取得するためにいくつかの魔法を実行できます。

@Autowired(required=false) 
    private BaseInterface[] theWorkers; 

これは、コンフィグレーションでBeanコンテナに追加した限り、私にワーカーBeanの配列を与えます。

私はGrailsで同じことをしようとしています。同じ数式は機能しません。 @Autowired部分をサービスに入れ、resources.groovy内にImpl1とImpl2を作成することは、その仕事をしていないようです。だから私は最高の解決策が何であるか疑問に思っています:

1)私はこの作業を非常に簡単にする簡単なものがありません。

2)ダフィモhereで提案されているものに類似したものを実行します。私は、カスタムファクトリを使ったresources.groovyに名前付きのBeanを作成します。そのファクトリは、特定のインタフェースを実装しているすべてのクラスを含むクラスを生成します。私は、そのサービスを持っているサービス/クラスを引っ張るための提案に似た何かを使用して、そのサービスが他の人がそれを処理するためのサブクラスを反復できるようにします。

3)resources.groovy内のそれぞれのImplクラスの名前付きBeanを作成し、それぞれの固有の名前を使用して、すべてをクラスに個別に注入します。このオプションは実際には拡張されず、多くのダイナミズムを与えませんが、機能します。

答えて

6

Springアプリケーションコンテキストにアクセスする場合は、getBeansOfTypeを呼び出して、指定されたインタフェースを実装する既知のすべてのBeanを返すか、指定された基本クラスを拡張します。だから私はresources.groovyに各Beanを登録するだけでなく、アプリケーションコンテキストへの参照を取得し、あなたのためのインターフェイスの実装を見つけるマネージャクラスです。あなたはそれらを順番に呼び出すと言っているので、Orderedインターフェイスも実装する必要があります。

ここでマネージャークラス(パッケージの正しいフォルダに/グルーヴィーのsrc /に入れて、あなたが好きに名前を変更)です:

package com.foo 

import org.springframework.beans.factory.InitializingBean 
import org.springframework.context.ApplicationContext 
import org.springframework.context.ApplicationContextAware 

class BaseInterfaceManager implements ApplicationContextAware, InitializingBean { 

    ApplicationContext applicationContext 

    List<BaseInterface> orderedImpls 

    void afterPropertiesSet() { 
     orderedImpls = applicationContext.getBeansOfType(BaseInterface).values().sort { it.order } 
    } 
} 

は、彼らがOrderedを実装するように、豆を変更後:

import org.springframework.core.Ordered; 

public class Impl1 implements BaseInterface, Ordered { 
    public void doSomething(){ 
     System.out.println("doing impl 1"); 
    } 

    public int getOrder() { 
     return 42; 
    } 
} 

import org.springframework.core.Ordered; 

public class Impl2 implements BaseInterface, Ordered { 
    public void doSomething(){ 
     System.out.println("doing impl 2"); 
    } 

    public int getOrder() { 
     return 666; 
    } 
} 

ですべての3つを登録(好きな豆の名前を使用):

beans = { 

    impl1(Impl1) 
    impl2(Impl2) 

    baseInterfaceManager(BaseInterfaceManager) 
} 

そしてあなたがbaseInterfaceManager豆のサービスやコントローラまたは何に依存性注入を追加し、順番に実装クラスをループするためにそれを使用することができます。

class FooService { 

    def baseInterfaceManager 

    void someMethod() { 
     for (impl in baseInterfaceManager.orderedImpls) { 
     impl.doSomething() 
     } 
    } 
} 
+0

私が考えていたクールな1つの方法は、2つの実装Beanを別の単純なBeanにラッピングすることでした。 BaseInterfaceManagerは実装(または実装されている実装の数)を認識していないため、このソリューションの方がはるかに優れています。ですから、resources.groovyだけが更新する必要があります。これはまさに私が目指しているものです。 Grailsコミュニティに追加してくれてありがとう、本当に素晴らしいです。 – Scott

関連する問題