[英]Injecting an implementation of a generic interface subtype using Guice
我定義了以下API:
public interface Input<I> {
Collection<? extends I> read();
}
public interface Transformer<O, I> {
Collection<? extends O> transform(Collection<? extends I> inputData);
}
public interface Output<O> {
void write(Collection<? extends O> output);
}
public interface Executor {
void execute();
}
以及以下實現:
public final class InputImpl implements Input<String> {
@Override
public Collection<? extends String> read() {
return asList("1", "2");
}
}
public final class TransformerImpl implements Transformer<Integer, String> {
@Override
public Collection<? extends Integer> transform(final Collection<? extends String> inputData) {
return inputData.stream().map(Integer::parseInt).collect(Collectors.toList());
}
}
public final class OutputImpl implements Output<Integer> {
@Override
public void write(final Collection<? extends Integer> output) {
System.out.println(output);
}
}
public final class ExecutorImpl<I, O> implements Executor {
private final Input<I> input;
private final Transformer<O, I> transformer;
private final Output<O> output;
@Inject
public ExecutorImpl(final Input<I> input, final Transformer<O, I> transformer, final Output<O> output) {
this.input = input;
this.transformer = transformer;
this.output = output;
}
public void execute() {
final Collection<? extends I> inputData = input.read();
final Collection<? extends O> outputData = transformer.transform(inputData);
output.write(outputData);
}
}
這是我嘗試將API綁定到上面的實現:
public final class ModuleImpl extends AbstractModule {
@Override
protected void configure() {
bind(new TypeLiteral<Input<String>>() {
}).to(InputImpl.class);
bind(new TypeLiteral<Transformer<Integer, String>>() {
}).to(TransformerImpl.class);
bind(new TypeLiteral<Output<Integer>>() {
}).to(OutputImpl.class);
bind(Executor.class).to(ExecutorImpl.class);
}
}
當我試圖使用Guice注入器獲取Executor
的實例時,我收到以下錯誤:
1) com.csc.playground.guice.api.Input<I> cannot be used as a key; It is not fully specified.
at com.csc.playground.guice.ExecutorImpl.<init>(ExecutorImpl.java:25)
at com.csc.playground.guice.module.ModuleImpl.configure(ModuleImpl.java:33)
2) com.csc.playground.guice.api.Transformer<O, I> cannot be used as a key; It is not fully specified.
at com.csc.playground.guice.ExecutorImpl.<init>(ExecutorImpl.java:25)
at com.csc.playground.guice.module.ModuleImpl.configure(ModuleImpl.java:33)
3) com.csc.playground.guice.api.Output<O> cannot be used as a key; It is not fully specified.
at com.csc.playground.guice.ExecutorImpl.<init>(ExecutorImpl.java:25)
at com.csc.playground.guice.module.ModuleImpl.configure(ModuleImpl.java:33)
從概念上講,問題出在這里:
@Inject
public ExecutorImpl(final Input<I> input,
final Transformer<O, I> transformer,
final Output<O> output) {
當guice嘗試實現Input<I>
的依賴時,它不知道它是什么類型; 這是“它沒有完全指定”的意思。
您可以通過指定泛型類型來解決此問題。 這樣做的方式與在AbstractModule
進行綁定的方式相同,例如,不是綁定到ExecutorImpl.class
,而是:
bind(Executor.class).to(new TypeLiteral<ExecutorImpl<String, Integer>>() {});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.