I have two implementations of interface IFoo
: Foo1
and Foo2
.
I need the context to be able to inject the correct one for any class that wants an IFoo
without that class knowing what implementation it's going to get (so no use of @Qualifier
).
Example of usage:
class Bar {
@Autowired IFoo foo;
}
I have a FactoryBean<IFoo>
class that has the logic for which one to return.
The issue is that I also want to have those two impls go through the IOC because they have dependencies themselves.
public class FooFactory implements FactoryBean<Foo> {
@Autowired Foo1 foo1;
@Autowired Foo2 foo2;
@Override
public IFoo getObject() throws Exception {
if(someLogic()){
return foo1;
}
return foo2;
}
}
If I autowire them into the factory I get an exception of
"No unique bean of type IFoo is defined: expected single matching bean but found 3: [fooFactory, foo1, foo2]"
Any way to tell spring to just use the default of fooFactory for everyone else but use the two implementations inside the factory?
You could use the notion of the "primary" bean. Assuming that you're using XML config, then:
<bean id="fooFactory" class="x.y.FooFactory" primary="true"/>
Now, @Autowired IFoo foo
should select the result of the factory, in preference to the foo1
and foo2
beans.
I would also recommend using @Resource
inside the factory itself, rather than @Autowired
, i.e.
public class FooFactory implements FactoryBean<Foo> {
@Resource Foo1 foo1;
@Resource Foo2 foo2;
This reduces the chance of the autowiring chasing its own tail, since @Resource
will inject a specific, named bean (i.e. foo1
and foo2
). You'd still use @Autowired
in Bar
.
If you use @Resource
like that, then an alternative to use primary="true"
is to exclude the foo1
and foo2
beans from autowiring, e.g.
<bean id="foo1" class="x.y.Foo1" autowire-candidate="false"/>