Reputation: 9499
I have a Spring based Java application where a lot of classes use the following autowired interface.. they work off this interface at all places.
@Autowired
private IOperatingSystemManager m_operatingSystemManager;
Right now, there is only one implementation of the interface as follows:
@Component
public class WindowsManager implements IOperatingSystemManager
{
// Windows based shenanigans
}
And the application works as expected. Spring is happy. Everybody is happy. Alright, not everybody...
So, I want to add another concrete implementation of IOperatingSystemManager
..
@Component
public class LinuxManager implements IOperatingSystemManager
{
// Linux based shenanigans
}
What we want is the auto wiring of IOperatingSystemManager conditionally based on a properties file setting. (say.. os=windows.. basically something that is an arbitrary string and cannot be derived from system properties etc. simply because this is a dummy example. the actual managers are not OS related.)
I don't want to change any of the classes who have autowired to the interface and are working off the interface. All I need is for Spring to look at some logic that will dictate the Autowiring of the variables and wire up the right concrete instance for:
@Autowired
IOperatingSystemManager m_operatingSystemManager
at all the gazillion places.
The documentation & web search talk about profiles, condition, bean factory, qualifiers etc.. but we don't want to use Profiles; and Qualifiers seem to be needing changes to all the interface variable annotations.
Factory methods look promising, but being new to Spring, couldn't find a crisp answer.
What is a simple and recommended way to achieve this?
Upvotes: 1
Views: 3304
Reputation: 3257
I dont know which version of spring you are using but you have options for this
http://www.intertech.com/Blog/spring-4-conditional-bean-configuration/
Here, as you can see, you can create a bean based on a condition that you can decide. It actully gave your example, Windows and Linux :), so i believe thats what you are looking for.
Edit:
If you are using spring-boot, you have some other Conditional annotations
Upvotes: 1
Reputation: 34460
Instead of scanning the WindowsManager
class, create one concrete instance that implements the IOperatingSystemManager
interface or another one, depending on the your logical conditions.
First, remove the @Component
annotation from the WindowsManager
class.
Then, create and scan this @Configuration
class, which will act as a factory for your beans:
@Configuration
public class OperatingSystemManagerFactory {
@Bean
public IOperatingSystemManager getOperatingSystemManager() {
if ( /* some logic that evaluates to true if windows */ ) {
return new WindowsManager();
} else {
// Linux default option ;)
return new LinuxManager();
}
}
}
With this solution, you shouldn't need to update anyone of your classes that reference the IOperatingSystemManager
interface.
Upvotes: 3