Reputation: 9938
Let's say I have this class
class Foo implements IFoo { Foo() {} }
class Fooz implements IFoo { Fooz() {}}
class Foobar implement IFoobar {
@Autowired
Foobar (Foo foo) {}
}
class Foobarz implement IFoobar {
@Autowired
Foobarz (Bar bar) {}
}
In asimple case I can do to solve my problem:
class Bar {
@Autowired
Bar (IFoo foo) {
this.foo = foo;
}
}
However if I want to be able to select my IFoo and IFoobar instance according to my configuration file I need to do do:
@Configuration
class Configuration {
@Bean
foo () {
return this.isZ() ? new Fooz() : new Foo ();
}
@Bean
foobar () {
return this.isZ() ? new Foobarz(/* ??????? */) : new Foobar (/* ??????? */);
}
}
As you can see I can't instantiate my Foobar, since I need another bean. I know there is the ApplicationContext.getBean, but I can't be sure it will be indeed initialized in my Configuration
class when foobar()
gets called.
And I don't want to call this.foo()
either, because that would create another reference of the object, and I'm not sure about the order of execution and initialization
Upvotes: 0
Views: 1287
Reputation: 7521
In your case following should do the trick
@Configuration
class Configuration {
@Bean
IFoo foo() {
return this.isZ() ? new Fooz() : new Foo ();
}
@Bean
IFoobar foobar(IFoo foo) { // IFoo bean declared above will be injected here by Spring
return this.isZ() ? new Foobarz(foo) : new Foobar(foo);
}
}
UPDATED
But more elegant way to do it is just to put @Service
or @Component
annotation on your class (@Bean
declaration should be removed from configuration though) ...
package com.foobarpkg.maybeanotherpkg;
@Service
class Foobar implement IFoobar {
@Autowired
Foobar (IFoo foo) { // not that interface should be used here instead of concrete class (Foo/Fooz)
}
}
... and let Spring know its package is located at
@Configuration
@ComponentScan(basePackages = {"com.foobarpkg"})
class Configuration {
@Bean
IFoo foo() {
return this.isZ() ? new Fooz() : new Foo ();
}
// foobar bean is no longer declared here
}
Upvotes: 1