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

Spring框架最强大的一个重点是dependency injection概念。 我理解其中的一个建议是将一般的高级机制与低级细节分开(如依赖性倒置原则所宣布的那样)。

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

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

但是如果我想要一个在多个依赖bean上运行的高级机制呢?

  public class MenuManagementBean { private Collection options; public void printOut() { for (Option option:options) { // do something for option } //... } } 

我知道一个解决方案是在单例bean中使用@Autowired注释,即……

  @Autowired private Collection options; 

但它不违反分离原则吗? 为什么我必须在我使用它们的同一个地方指定依赖者(即我的例子中的MenuManagementBean类)? 有没有办法像这样在XML配置中注入bean集合(在MMB类中没有任何注释)?

      

没有开箱即用的设施可以做到这一点,没有。 但是,如果您想要一种将给定类型的所有bean收集到集合中而不使用@Autowired列表的方法,那么可以轻松编写自定义FactoryBean来为您执行此操作:

 public class BeanListFactoryBean extends AbstractFactoryBean> { private Class beanType; private @Autowired ListableBeanFactory beanFactory; @Required public void setBeanType(Class beanType) { this.beanType = beanType; } @Override protected Collection createInstance() throws Exception { return beanFactory.getBeansOfType(beanType).values(); } @Override public Class getObjectType() { return Collection.class; } } 

接着

         

然而,这一切似乎都是为了避免将@Autowired放入原始课程中。 如果它完全没有太多违反SoC的话 – 没有编译时间依赖性,也不知道options的来源。

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

 public class PluginPrototypeTest extends ASpringWebTest { @Autowired Collection 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"; } } 

@Autowired的替代方案,使用上下文文件: http : //static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire

所以你有:

  

其他属性可以像往常一样指定,并且只会覆盖那些属性的自动assembly。