8

在 Spring 中有没有一种方法可以自动填充一个类型的所有 bean 及其任何子类型的列表?我有一个看起来像这样的setter方法:

setMyProp(List<MyType> list)

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

谢谢,杰夫

4

5 回答 5

26

是的,你可以这样做。春季文档说:

还可以通过将注释添加到需要该类型数组的字段或方法来从 ApplicationContext 提供特定类型的所有 bean。

请注意,它说您需要一个数组,而不是一个列表。这是有道理的,因为泛型类型擦除意味着列表可能在运行时不起作用。但是,请进行以下单元测试,该测试有效:

<?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 {}

}

所以正式地说,你应该 autowire TypeA[],而不是List<TypeA>,但 List 效果很好。

于 2009-09-20T08:55:21.140 回答
5

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

于 2009-09-20T07:56:35.830 回答
3

如果您可以 @Autowired在要填充的代码内部使用,则可以安全地使用 skaffman 提到的方式。如果你坚持使用 XML 配置,有一个名为Hera的小库可以实现这一点。您描述的场景的基本配置如下所示:

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

SuperType这会将所有实现as的顶级 Spring beanList注入到客户端 bean 中。

于 2009-09-22T12:28:56.200 回答
0

简短的回答:没有。

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

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

可能有几种方法可以做到这一点。一种是创建 bean 后处理器。这样,您将收到有关创建的每个 bean 的通知。

于 2009-09-20T02:53:01.613 回答
0

由于遗留代码和缺少@Autowired,我解决它的方式如下:

MyBean implements ApplicationContextAware{

  @Override
  public void setApplicationContext(ApplicationContext ctx) throws BeansException {
    final Map<String, HttpRequestHandlerTemplate> beansOfType = ctx.getBeansOfType(RequiredBean.class);
    ...
}
于 2015-09-29T14:19:03.023 回答