2009-09-20 11 views
7

Springの型とすべてのサブタイプのBeanを自動的にリストに入れる方法はありますか?タイプ別のSpringリストBean

setMyProp(List<MyType> list) 

そして私はがMyTypeとがMyTypeのすべてのサブクラスのいずれかの豆でautowireしたい:私は次のようになりますsetterメソッドを持っています。

おかげで、 ジェフ

+0

このリストはプロトタイプで仕事をしたいどうすればよいですか?インスタンスが1つしか含まれていない場合は、各インスタンスを追加(メモリリーク)するか、何らかの形の弱い参照リストを返すようにしてください。 –

+0

私の場合、すべてのBeanはシングルトンになります –

答えて

24

よろしくお願いします。ばねドキュメントは言う:

それ がそのタイプの配列を期待フィールドまたはメソッドに アノテーションを追加することによって のApplicationContextから特定のタイプのすべての 豆を提供することも可能です。

リストではなく配列を期待する必要があることに注意してください。ジェネリック型の消去とは、実行時にリストが機能しない可能性があるためです。しかし、これは動作しますが、以下のユニットテストを取る:

<?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-2.5.xsd"> 

    <bean class="test.Test.TypeB"/> 
    <bean class="test.Test.TypeC"/> 
    <bean class="test.Test.TypeD"/> 
</beans> 

と、このユニットテスト:

package test; 

@ContextConfiguration 
@RunWith(SpringJUnit4ClassRunner.class) 
public class Test { 

    private @Autowired List<TypeA> beans; 

    @org.junit.Test 
    public void test() { 
     assertNotNull(beans); 
     assertEquals(2, beans.size()); 
     for (TypeA bean : beans) { 
      assertTrue(bean instanceof TypeA); 
     } 
    }  

    public static interface TypeA {} 
    public static class TypeB implements TypeA {} 
    public static class TypeC extends TypeB {} 
    public static class TypeD {} 

} 

だから正式に、あなたはTypeA[]、ないList<TypeA>をautowireことになっているが、リストには良い作品。

0

短い答え:いいえ。

長い答え:Javaジェネリックは、タイプ消去によって動作します。つまり、実行時に、このパラメータは単純なリストであり、ジェネリック型のリストではありません。このように、パラメータ型MyTypeであることがわかりませんので、この動作を実装することはできません。

これは、これを行う別の方法があります。最も明白なのは、Beanの作成を聞いて、それらがMyType(またはサブクラス)であるかどうかを確認してから、参照を保持することです。

これはおそらくいくつかの方法があります。 1つはcreating a bean post-processorです。この方法で、作成されたすべてのBeanを通知されます。

+3

メソッドのパラメータの型情報は完全には消去されておらず、ランタイムでも利用可能です。このメソッドには、メソッドまたはコンストラクターのgetGenericParameterTypesメソッドを使用してアクセスできます。 –

+0

@mik:はい、しかし、彼はそのような情報が利用できない関数のパラメータについて話していました。 – cletus

5

ビーン定義ファイルからではなく、アプリケーションコードからリストを入力することが可能な場合は、org.springframework.beans.factory.xml.XmlBeanFactoryを使用して "getBeansOfType(MyType.class)"と尋ねることができます。これにより、すべてのタイプ(およびサブタイプ)の豆がMyTypeになります。

+1

これは実際にListableBeanFactory(http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/beans/factory/ListableBeanFactory.html#getBeansOfType%28java.lang.Class%)を実装するすべてのクラスで機能します。 29) –

3

コード内に@Autowiredを使用すれば、安全にskaffmanの言及した方法を使用できます。 XML構成を主張する場合は、これを実現するためにHeraという小さなライブラリがあります。自分で説明したシナリオのEsentially構成は次のようになります。

<bean id="client" class=".."> 
    <property name="injectDynamicListHere"> 
     <hera:list class="my.custom.SuperType" /> 
    </property> 
</bean> 

これは、クライアントBeanにListとしてSuperTypeを実装するすべてのトップレベルのSpring Beanを注入します。私はそれを解決するため、レガシーコードと行方不明@Autowiredへ

+0

クール、ありがとう。私はコードで@Autowiredを使用することができましたが、これは知っておくと良いことです。 –

+1

Heraリストが@Ordered注釈respを尊重していることは、おそらく1つの小さな問題です。 Orderedインタフェースを実装して、注入されたBeanの順序を決定できます。 –

0

が好き:

MyBean implements ApplicationContextAware{ 

    @Override 
    public void setApplicationContext(ApplicationContext ctx) throws BeansException { 
    final Map<String, HttpRequestHandlerTemplate> beansOfType = ctx.getBeansOfType(RequiredBean.class); 
    ... 
} 
関連する問題