Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在SpringXML配置中收集和注入给定类型的所有bean_Java_Spring_Dependency Injection - Fatal编程技术网

Java 如何在SpringXML配置中收集和注入给定类型的所有bean

Java 如何在SpringXML配置中收集和注入给定类型的所有bean,java,spring,dependency-injection,Java,Spring,Dependency Injection,Spring框架最突出的特点之一是概念。我理解其中一个建议是将一般的高层机制与低层细节分开(如所宣布的) 从技术上讲,这归结为让bean实现尽可能少地了解作为依赖项注入的bean,例如 public class PrintOutBean { private LogicBean logicBean; public void action() { System.out.println(logicBean.humanReadableDetails()); }

Spring框架最突出的特点之一是概念。我理解其中一个建议是将一般的高层机制与低层细节分开(如所宣布的)

从技术上讲,这归结为让bean实现尽可能少地了解作为依赖项注入的bean,例如

public class PrintOutBean {
    private LogicBean logicBean;
    public void action() {
        System.out.println(logicBean.humanReadableDetails());
    }
    //...
}

<bean class="PrintOutBean">
    <property name="loginBean" ref="ShoppingCartBean"/>
</bean>
但这不是违反了分离原则吗?为什么我必须指定在我使用依赖项的同一位置(即我的示例中的
MenuManagementBean
类)接受哪些依赖项? 有没有一种方法可以像这样在XML配置中注入bean集合(在
MMB
类中没有任何注释)


没有现成的工具可以做到这一点,没有。但是,如果您想在不使用@Autowired列表的情况下将给定类型的所有bean收集到一个集合中,那么编写自定义的
FactoryBean
就很容易了:

public class BeanListFactoryBean<T> extends AbstractFactoryBean<Collection<T>> {

    private Class<T> beanType;
    private @Autowired ListableBeanFactory beanFactory;

    @Required
    public void setBeanType(Class<T> beanType) {
        this.beanType = beanType;
    }

    @Override
    protected Collection<T> createInstance() throws Exception {
        return beanFactory.getBeansOfType(beanType).values();
    }

    @Override
    public Class<?> getObjectType() {
        return Collection.class;
    }    
}
公共类BeanListFactoryBean扩展了AbstractFactoryBean{
私有类beanType;
private@Autowired ListableBeanFactory beanFactory;
@必需的
公共类型(类beanType){
this.beanType=beanType;
}
@凌驾
受保护的集合createInstance()引发异常{
返回beanFactory.getBeansOfType(beanType.values();
}
@凌驾
公共类getObjectType(){
返回集合.class;
}    
}
然后

 <bean class="MenuManagementBean">
    <property name="options">
       <bean class="BeanListFactoryBean">
          <property name="beanType" class="MyOptionImpl.class"/>
       </bean>
    </property>
 </bean>


然而,这一切似乎都是为了避免将
@Autowired
放入原始类中。如果有违反SoC的行为,那也算不上违反SoC——没有编译时间依赖关系,也不知道
选项的来源。

使用上下文文件替代@Autowired:

所以你会:

<bean class="MenuManagementBean" autowire="byType" />


正常情况下,可以指定其他属性,这将仅覆盖这些属性的自动关联。

旧问题,在Spring 3.1中,可能:

public class PluginPrototypeTest extends ASpringWebTest {
  @Autowired
  Collection<IDummyRepo> repos;

  @Test
  public void cacheTest() {
    assertNotNull(repos);
    assertEquals(2, repos.size());
    for(IDummyRepo r: repos){
      System.out.println(r.getName());
    }
  }
}

@Repository
public class DummyRepo implements IDummyRepo {
  @Override
  public String getName(){
    return "DummyRepo";
  }
}
@Repository
public class DummyRepo2 implements IDummyRepo {
  @Override
  public String getName(){
    return "DummyRepo2";
  }
}
公共类PluginPrototypeTest扩展了ASpringWebTest{
@自动连线
收款回购;
@试验
公共void cacheTest(){
资产不为空(回购);
资产质量(2,repos.size());
用于(IDummyRepo r:repos){
System.out.println(r.getName());
}
}
}
@存储库
公共类DummyRepo实现IDummyRepo{
@凌驾
公共字符串getName(){
返回“DummyRepo”;
}
}
@存储库
公共类dummyrepo实现了IDummyRepo{
@凌驾
公共字符串getName(){
返回“DummyRepo2”;
}
}

我不认为将@Autowired添加到字段会为您创建选项集合-您仍然需要在上下文中声明一个列出选项的bean。然后,您也可以删除@Autowired并在MMB上下文定义中放置一个。@mdma:我很确定,将
@Autowired
添加到集合属性可以收集集合元素类型的所有bean。这就是我们一直使用它的方式。Spring2.5doconIt:好的,很好,很好的特性!我确实检查了文件,但我看的时候没有看到。很抱歉造成混淆。我已经向Spring framework报告了一个功能请求,其中包括:@Grzegorz-Oledzki与这个问题并不完全相关,但是当使用Java配置而不是XML文件时,自动连线是否有效?看起来它的工作方式不一样。我认为Resource在使用Java配置时会这样做,而不是自动连接。Custom FactoryBean:乍一看,我想这个解决方案不允许我指定两个(或更多)集合按类型自动连接并作为单个集合注入。我在问题中没有说明这一点,但我认为它可能有用。当涉及到SoC违规时:我明白你的观点,但我仍然认为它有问题。如果我应该在我的库中开发和交付高级bean(
MenuManagementBean
),然后一些依赖的项目应该能够使用它呢?@Grzegorz:向工厂bean注入
选项.class
,而不是
MyOptionImpl.class
,这应该可以让所有bean实现接口。嗯。。。也许它没有那么实用,但我认为如果只注入
选项
接口的一些实现将是有益的。特别是如果
选项
接口非常通用(有很多子接口和类)。@Grzegorz:好的,那么修改工厂bean以获取类型列表,并使其将这些类型的所有bean添加到同一个集合中。我相信最初的请求是避免使用注释,而不是避免使用XML。。。
 <bean class="MenuManagementBean">
    <property name="options">
       <bean class="BeanListFactoryBean">
          <property name="beanType" class="MyOptionImpl.class"/>
       </bean>
    </property>
 </bean>
<bean class="MenuManagementBean" autowire="byType" />
public class PluginPrototypeTest extends ASpringWebTest {
  @Autowired
  Collection<IDummyRepo> repos;

  @Test
  public void cacheTest() {
    assertNotNull(repos);
    assertEquals(2, repos.size());
    for(IDummyRepo r: repos){
      System.out.println(r.getName());
    }
  }
}

@Repository
public class DummyRepo implements IDummyRepo {
  @Override
  public String getName(){
    return "DummyRepo";
  }
}
@Repository
public class DummyRepo2 implements IDummyRepo {
  @Override
  public String getName(){
    return "DummyRepo2";
  }
}