我有两个接口IFoo
的实现:Foo1
和Foo2
。
我需要上下文能够为任何想要IFoo
的类注入正确的上下文而不知道它将获得什么实现(因此不使用@Qualifier
)。
使用示例:
class Bar {
@Autowired IFoo foo;
}
我有一个FactoryBean<IFoo>
类,其中包含返回的逻辑。
问题在于我也想让这两个人通过IOC,因为他们自己有依赖。
public class FooFactory implements FactoryBean<Foo> {
@Autowired Foo1 foo1;
@Autowired Foo2 foo2;
@Override
public IFoo getObject() throws Exception {
if(someLogic()){
return foo1;
}
return foo2;
}
}
如果我将它们自动装入工厂,我会得到
的例外"No unique bean of type IFoo is defined: expected single matching bean but found 3: [fooFactory, foo1, foo2]"
任何方式告诉spring只为其他人使用默认的fooFactory但是在工厂内使用这两个实现?
答案 0 :(得分:1)
您可以注入一个列表:
@Resource
private List<IFoo> foos;
不幸的是,由于您当前正在构建FooFactory
,因此可能无效,因此您可能会遇到循环依赖性错误。试试吧!
但是自从Spring 3.1开始使用@Profile
或@Configuration
时,更惯用的操作:
@Bean
public IFoo foo() {
if(someCondition) {
return new Foo1(dep1(), dep2());
else
return new Foo1(dep3(), dep4());
}
其中dep...()
方法也是@Bean
声明。
答案 1 :(得分:1)
您可以使用@Primary
来修改工厂结果。
我还没有尝试过,并且没有IDE来测试它,但可能有效。
@Configuration
public class MyFactory {
@Bean
@Primary
public IFoo getFoo () {
...
}
}
答案 2 :(得分:1)
您可以使用“主要”bean的概念。假设您正在使用XML配置,那么:
<bean id="fooFactory" class="x.y.FooFactory" primary="true"/>
现在,@Autowired IFoo foo
应该选择工厂的结果,而不是foo1
和foo2
bean。
我还建议在工厂内使用@Resource
,而不是@Autowired
,即
public class FooFactory implements FactoryBean<Foo> {
@Resource Foo1 foo1;
@Resource Foo2 foo2;
这降低了自动装配追逐自己尾部的几率,因为@Resource
将注入一个特定的命名bean(即foo1
和foo2
)。您仍在@Autowired
中使用Bar
。
如果您使用@Resource
,那么使用primary="true"
的替代方法是从自动装配中排除foo1
和foo2
bean,例如
<bean id="foo1" class="x.y.Foo1" autowire-candidate="false"/>
答案 3 :(得分:0)
看一下bean工厂范围。