我现在已经随便使用guice了一段时间,但还不足以弄清楚如何在这种情况下完成我想要的东西。我似乎想要AssistedInject
,Throwing Providers
和Multibindings
的某种组合,但我不确定如何将它们整合在一起。这是一个没有完成工作的简化代码。它需要是Guicier!
public class Utilities {
public static String expensiveLookup(String key) throws IOException {...}
}
public class Helper {
@Inject private InjectedClass injectedValue;
public Helper(String value1, String value2, String value3) {...}
}
public class Workhorse {
// This map isn't very guicy. I'd prefer named bindings, or a multibinding
private static Map<String, Helper> helpers = new HashMap();
public static void register(String name, Helper helper) {
helpers.put(name, helper);
}
////////
@Inject lots of things
public void doHardWork(String helperName) {
Helper helper = helpers.get(helperName);
// do something hard
}
}
class UserModule extends AbstractModule {
protected void configure() {
// Helpers are created with `new`, so they don't get `injectedValue`
Workhorse.register("cheap helper", new Helper("cheap value", ...));
try {
// This expensive lookup should be delay until needed
String expensiveValue = Utilities.expensiveLookup("expensive key");
Workhorse.register("expensive helper", new Helper(expensiveValue, ...));
} catch (IOException ex) {
// This exception should be handled in `doHardwork()`
}
}
}
我可以弄清楚如何一次解决任何两个问题,但不是全部4:
Helper
需要使用Guice创建,而不是new
expensiveLookup
应该延迟到需要IOException
doHardWork
helpers
映射应该可以用命名绑定或多绑定替换。这对我来说不是一个严格的要求,但似乎是正确的。有人可以提供一些提示吗?
答案 0 :(得分:0)
好吧,我终于找到了解决方案。我对它一定不满意,因为它需要大约两倍的代码并且难以理解,但它确实有效。我真诚地希望有一种更简单的方法。
public class Utilities {
public static String expensiveLookup(String key) throws IOException {...}
}
public class Helper {
private InjectedClass injectedValue;
@Inject
public Helper(
@Assisted("value1") String value1,
@Assisted("value2") String value2,
@Assisted("value3") String value3,
InjectedClass injectedValue) {
this.injectedValue = injectedValue;
...
}
public static <T extends Provider> void installProvider(
Binder binder, String name, Class<T> providerClass) {
ThrowingProviderBinder.create(binder)
.bind(ProviderInterface.class, Helper.class)
.annotatedWith(Names.named(name))
.to(providerClass)
.in(Singleton.class);
}
abstract public static Provider implements ProviderInterface {
@Inject private Factory factory;
protected Helper expensiveBuild(
String expensiveKey,
String value2,
String value3) throws IOException {
String expensiveValue = Utilities.expensiveLookup(expensiveKey);
return cheapBuild(expensiveValue, value2, value3);
}
protected Helper cheapBuild(String value1, String value2, String value3) {
return Factory.create(value1, value2, value3);
}
}
interface ProviderInterface extends CheckedProvider<Helper> {
public Helper get() throws IOException;
}
interface Factory {
Helper create(
@Assisted("value1") String value1,
@Assisted("value2") String value2,
@Assisted("value3") String value3);
}
}
class HelperModule exends AbstractModule {
protected void configure() {
install(new FactoryModuleBuilder()
.implement(Helper.class, Helper.class)
.build(Helper.Factory.class));
}
}
public class Workhorse {
@Inject lots of things
@Inject private Injector injector;
public void doHardWork(String helperName) {
Key key = Key.get(Helper.ProviderInterface.class, Names.named(helperName));
try {
Helper helper = injector.getInstance(key).get(helperName);
// do something hard
} catch (IOException ex) {
...
}
}
}
class UserModule extends AbstractModule {
protected void configure() {
Helper.installProvider(binder(), "cheap helper", CheapProvider.class);
Helper.installProvider(binder(), "expensive helper", ExpensiveProvider.class);
}
private static class CheapProvider extends Provider {
public Helper get() {
return cheapBuild("cheap value", ...);
}
}
private static class ExpensiveProvider extends Provider {
public Helper get() throws IOException {
return expensiveBuild("expensive key", ...);
}
}
}
如果有人有更好的答案我会喜欢它!