How to collect and inject all beans of a given type in Spring XML configuration

Old question and in Spring 3.1 it is possible:

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";
  }
}

There's no out-of-the-box facility to do this, no. However, if you want a way of collecting all beans of a given type into a collection, without using an @Autowired list, then it's easy to write a custom FactoryBean to do it for you:

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;
    }    
}

and then

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

However, this all seems like a lot of effort to avoid putting @Autowired in your original class. It's not much of a violation of SoC, if it is at all - there's no compiltime dependency, and no knowledge of where the options are coming from.


Alternative to @Autowired, using a context file: http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire

So you'd have:

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

Other properties can be specified, as normal, and that would override the autowiring only for those properties.