Raja Nadar
Raja Nadar

Reputation: 9499

Interface to concrete class conditional instantiation in Spring

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

Answers (2)

Gokhan Oner
Gokhan Oner

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

http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html#boot-features-condition-annotations

Upvotes: 1

fps
fps

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

Related Questions