[英]How to collect and inject all beans of a given type in Spring XML configuration
One of the strongest accents of the Spring framework is the Dependency Injection concept. Spring框架最强大的一个重点是依赖注入概念。 I understand one of the advices behind that is to separate general high-level mechanism from low-level details (as announced by Dependency Inversion Principle ).
我理解其中的一个建议是将一般的高级机制与低级细节分开(如依赖性倒置原则所宣布的那样)。
Technically, that boils down to having a bean implementation to know as little as possible about a bean being injected as a dependency, eg 从技术上讲,这可以归结为让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>
But what if I wanted to a have a high-level mechanism operating on multiple dependent beans? 但是,如果我想要一个在多个依赖bean上运行的高级机制呢?
public class MenuManagementBean {
private Collection<Option> options;
public void printOut() {
for (Option option:options) {
// do something for option
}
//...
}
}
I know one solution would be to use @Autowired
annotation in the singleton bean, that is... 我知道一个解决方案是在单例bean中使用
@Autowired
注释,即......
@Autowired
private Collection<Option> options;
But doesn't it violate the separation principle? 但它不违反分离原则吗? Why do I have to specify what dependents to take in the very same place I use them (ie
MenuManagementBean
class in my example)? 为什么我必须在我使用它们的同一个地方指定依赖项(即我的示例中的
MenuManagementBean
类)? Is there a way to inject collections of beans in the XML configuration like this (without any annotation in the MMB
class)? 有没有办法像这样在XML配置中注入bean集合(在
MMB
类中没有任何注释)?
<bean class="MenuManagementBean">
<property name="options">
<xxx:autowire by-type="MyOptionImpl"/>
</property>
</bean>
Old question and in Spring 3.1 it is possible: 旧问题,在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";
}
}
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: 但是,如果您想要一种将给定类型的所有bean收集到一个集合中而不使用@Autowired列表的方法,那么可以轻松编写自定义
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;
}
}
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. 但是,这一切似乎都是为了避免将
@Autowired
放在原来的课堂上。 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. 如果它完全没有太多违反SoC的话 - 没有编译时间依赖性,并且不知道
options
的来源。
Alternative to @Autowired, using a context file: http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-autowire @Autowired的替代方案,使用上下文文件: 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. 其他属性可以像往常一样指定,并且只会覆盖那些属性的自动装配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.