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?
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.