【问题标题】:Spring list beans by typeSpring 按类型列出 bean
【发布时间】:2009-09-20 02:41:04
【问题描述】:

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

setMyProp(List<MyType> list)

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

谢谢, 杰夫

【问题讨论】:

  • 您希望此列表如何与原型一起使用?如果它只包含一个实例,则添加每个实例(内存泄漏)或通过某种形式的弱引用列表返回。
  • 在我的情况下,所有的 bean 都将是单例

标签: java spring autowired


【解决方案1】:

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

也可以提供所有 特定类型的豆类 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&lt;TypeA&gt;,但列表效果很好。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    【解决方案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 中。

    【讨论】:

    • 酷,谢谢。我能够在代码中使用@Autowired,但很高兴知道这一点。
    • 也许要添加的一件小事是 Hera 列表尊重 @Ordered 注释。实现 Ordered 接口以允许确定注入的 bean 的顺序。
    【解决方案4】:

    简短回答:不。

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

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

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

    【讨论】:

    • 方法参数的类型信息并未完全擦除,运行时仍可使用。您可以通过 Method 或 Constructor getGenericParameterTypes 方法访问它。
    • @mik:是的,但他在谈论一个函数的参数,没有这样的信息可用。
    【解决方案5】:

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

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

    【讨论】:

      猜你喜欢
      • 2017-01-13
      • 2015-08-02
      • 1970-01-01
      • 1970-01-01
      • 2018-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多