title: Spring: how to change interface implementations at runtime
body: <p>As a Java developer I frequently need to choose between different implementations of my interfaces. Sometimes this choice can be done <em>once</em>, 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 <em>change</em> 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.</p>
  
  <p>With Spring I can design such an object as a bean and inject it wherever I need:</p>
  
  <pre><code>public class MyClass {
  
      @Autowired
      private MyHelper helper;
  
      public void someMethod(String someKey) {
          AnInterface i = helper.giveMeTheRightImplementation(someKey);
          i.doYourjob();
      }
  
  }
  </code></pre>
  
  <p>Now, how should I implement the helper? Let's start with this:</p>
  
  <pre><code>@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 ...
      }
  
  }
  </code></pre>
  
  <p>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 <code>Foo</code> class like this:</p>
  
  <pre><code>@Service
  public class Foo {
  
      @Autowired
      private VeryCoolService coolService;
  
      ...
  
  }
  </code></pre>
  
  <p>...instances of <code>Foo</code> returned by <code>MyHelper</code> won't have the <code>coolService</code> field properly initialized.</p>
  
  <p>To avoid this, a frequently suggested workaround is to inject <em>each possible implementation</em> inside the helper:</p>
  
  <pre><code>@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 ...
      }
  
  }
  </code></pre>
  
  <p>But I'm not a big fan of such solutions. I find more elegant and maintainable something like this:</p>
  
  <pre><code>@Service
  public class MyHelper {
  
      @Autowired
      private ApplicationContext app;
  
      public AnInterface giveMeTheRightImplementation(String key) {
          return (AnInterface) app.getBean(key);
      }
  
  }
  </code></pre>
  
  <p>This is based on Spring's <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ApplicationContext.html" rel="noreferrer">ApplicationContext</a>.</p>
  
  <p>A similar solution is to use the <a href="http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/ServiceLocatorFactoryBean.html" rel="noreferrer">ServiceLocatorFactoryBean</a> class:</p>
  
  <pre><code>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;
  }
  </code></pre>
  
  <p>But since I'm not a Spring expert I wonder if there are even better approaches.</p>