As a Java developer I frequently need to choose between different implementations of my interfaces. Sometimes this choice can be done once, while some other times I need different implementations in response to the different inputs that my program receives. In other words, I need to be able to change implementation at runtime. This is easily achievable through an helper object that converts some key (based on user input) into a reference to a suitable interface implementation.
With Spring I can design such an object as a bean and inject it wherever I need:
public class MyClass {
    @Autowired
    private MyHelper helper;
    public void someMethod(String someKey) {
        AnInterface i = helper.giveMeTheRightImplementation(someKey);
        i.doYourjob();
    }
}
Now, how should I implement the helper? Let's start with this:
@Service
public class MyHelper {
    public AnInterface giveMeTheRightImplementation(String key) {
        if (key.equals("foo")) return new Foo();
        else if (key.equals("bar")) return new Bar();
        else ...
    }
}
Such a solution has several flaws. One of the worst is the fact that instances returned from the helper are unknown to the container and thus cannot benefit from dependency injection. In other words, even if I define  the Foo class like this:
@Service
public class Foo {
    @Autowired
    private VeryCoolService coolService;
    ...
}
...instances of Foo returned by MyHelper won't have the coolService field properly initialized.
To avoid this, a frequently suggested workaround is to inject each possible implementation inside the helper:
@Service
public class MyHelper {
    @Autowired
    private Foo foo;
    @Autowired
    private Bar bar;
    ...
    public AnInterface giveMeTheRightImplementation(String key) {
        if (key.equals("foo")) return foo;
        else if (key.equals("bar")) return bar;
        else ...
    }
}
But I'm not a big fan of such solutions. I find more elegant and maintainable something like this:
@Service
public class MyHelper {
    @Autowired
    private ApplicationContext app;
    public AnInterface giveMeTheRightImplementation(String key) {
        return (AnInterface) app.getBean(key);
    }
}
This is based on Spring's ApplicationContext.
A similar solution is to use the ServiceLocatorFactoryBean class:
public interface MyHelper {
    AnInterface giveMeTheRightImplementation(String key);
}
// Somewhere else, in Java config
@Bean
ServiceLocatorFactoryBean myHelper() {
    ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean();
    bean.setServiceLocatorInterface(MyHelper.class);
    return bean;
}
But since I'm not a Spring expert I wonder if there are even better approaches.
 
     
     
    