Spring按类型列出bean

时间:2009-09-20 02:41:04

标签: java spring autowired

在Spring中是否有一种方法可以使用类型及其任何子类型的所有bean自动填充列表?我有一个看似如下的setter方法:

setMyProp(List<MyType> list)

我想在MyType的所有bean和MyType的所有子类中自动装配。

谢谢, 杰夫

5 个答案:

答案 0 :(得分: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>,但是List工作得很好。

答案 1 :(得分:5)

如果从应用程序代码中填充列表是可以接受的,而不是从bean定义文件中填写,则可以使用org.springframework.beans.factory.xml.XmlBeanFactory并询问它“getBeansOfType( MyType.class )”。这将为您提供MyType类型(和子类型)的所有bean。

答案 2 :(得分:3)

如果您可以在要填充的代码中使用@Autowired,则可以安全地使用skaffman提到的方式。如果您坚持使用XML配置,那么可以使用一个名为Hera的小型库来实现此目的。您描述的场景的基本配置如下所示:

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

这会将实现SuperType List的所有顶级Spring bean注入客户端bean。

答案 3 :(得分:0)

简答:不。

长答案:Java泛型按类型擦除工作,这意味着在运行时该参数只是一个List,而不是泛型类型的List。因此,您无法确定它是否属于参数类型MyType,因此无法实现此行为。

话虽如此,还有其他方法可以做到这一点。最明显的似乎是监听bean创建,然后查看它们是否属于MyType(或子类),然后保留引用。

可能有几种方法可以做到这一点。一个是creating a bean post-processor。通过这种方式,您将收到所有创建的bean的通知。

答案 4 :(得分:0)

由于遗留代码和@Autowired丢失,我解决了它:

MyBean implements ApplicationContextAware{

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