我有一个没有main方法的类。此类也由不在我控制范围内的代码使用。该类有一个方法,它将String作为参数,然后根据该String的值创建不同的对象。我如何使用Guice创建这些对象?我认为答案与提供商有关,但我不确定如何实现它。
这是有问题的类,它不使用DI来制作对象:
public class ActionHandler {
public void doSomething(String message) throws Exception {
ActionObject actionObj = null;
if (message.equals("dog")) {
// ActionObjectDog implements ActionObject
actionObj = new ActionObjectDog();
}
else if (message.equals("cat")) {
// ActionObjectCat implements ActionObject
actionObj = new ActionObjectCat();
}
else {
throw new Exception("Action " + message + " not implemented.");
}
actionObj.run();
}
}
我试图注入一个Provider,但是我遇到了困难,因为我无法弄清楚如何使Provider get()方法返回ActionObject的特定实现。
@Inject private Provider<ActionObject> actionObjectProvider;
有什么想法?
答案 0 :(得分:2)
Provider
对您的情况不起作用,因为正如您所发现的那样,get()
不会采用任何参数。
一种选择是使用MapBinder
:
class Module extends AbstractModule {
@Override protected void configure() {
MapBinder.newMapBinder(binder(), String.class, ActionObject.class)
.addBinding("dog").to(ActionObjectDog.class);
MapBinder.newMapBinder(binder(), String.class, ActionObject.class)
.addBinding("cat").to(ActionObjectCat.class);
}
}
class ActionHandler {
private final Map<String, ActionObject> mappings;
@Inject ActionHandler(Map<String, ActionObject> mappings) {
this.mappings = mappings;
}
public void doSomething(String message) {
Preconditions.checkNotNull(mappings.get(message), "No action for '" + message + "'")
.run();
}
}
它没有利用任何令人敬畏的Guiciness,但它将ActionObject
选择逻辑移出ActionHandler
,这听起来就像你正在尝试做的那样。注入的映射只是Collections.UnmodifiableMap
,因此每次调用mappings.get(...)
时都会返回相同的实例,这意味着您的ActionObject
实现需要线程安全。
另外,我对缺乏main
方法的特别关注感到困惑。也许我误解了这个问题,但你可以从任何你想要的地方创建一个Guice Injector
。如果上述解决方案不适合您,您可以扩展该限制吗?