作为一名 Java 开发人员,我经常需要在接口的不同实现之间进行选择。有时这种选择是可以做到的once,而有时我需要不同的实现来响应我的程序收到的不同输入。换句话说,我需要能够change运行时执行。这可以通过帮助程序对象轻松实现,该对象将某些键(基于用户输入)转换为对合适接口实现的引用。
使用 Spring,我可以设计一个像 bean 这样的对象,并将其注入到任何我需要的地方:
public class MyClass {
@Autowired
private MyHelper helper;
public void someMethod(String someKey) {
AnInterface i = helper.giveMeTheRightImplementation(someKey);
i.doYourjob();
}
}
现在,我应该如何实现这个助手?让我们从这个开始:
@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 ...
}
}
这种解决方案有几个缺陷。最糟糕的情况之一是容器不知道从帮助器返回的实例,因此无法从依赖项注入中受益。换句话说,即使我定义Foo
像这样的类:
@Service
public class Foo {
@Autowired
private VeryCoolService coolService;
...
}
...实例Foo
由返回MyHelper
不会有coolService
字段已正确初始化。
为了避免这种情况,经常建议的解决方法是注入每个可能的实现助手内部:
@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 ...
}
}
但我不太喜欢这样的解决方案。我发现更优雅和可维护的东西是这样的:
@Service
public class MyHelper {
@Autowired
private ApplicationContext app;
public AnInterface giveMeTheRightImplementation(String key) {
return (AnInterface) app.getBean(key);
}
}
这是基于 Spring 的应用上下文.
类似的解决方案是使用服务定位器工厂Bean 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;
}
但由于我不是 Spring 专家,我想知道是否有更好的方法。