[英]Binding a generic abstract super class to multiple non-generic implementation classes
我相信我的设置有点不合常规,所以解释会更长一些。 我有一个抽象的超class,用方法
public abstract T execute(P parameters);
我有一组扩展它的实现类,并在扩展语句中分配单独的类型。 这意味着实现不是通用的。
我通过注释@Example 获取所有实现。 我使用 ClassGraph 来提取有关这些类的信息。 通过它,我不仅获得了实现,还获得了具有已定义类型的正确超类。
但是我现在无法使用 Guice bind().to();
为了提供更多背景...
我有一组实现类,它们与外部 API 通信。 每个 class 都与一个单独的区域通信。 我希望我自己的服务 API 不依赖于特定的实现。 我看不到未来,很有可能我们需要在以后更灵活地绑定实现(例如,同一个调用有 3 个不同的实现)。 外部服务是高度灵活的,因此消费者必须具有类似的灵活性。
出于这个原因,我的目标是使用 guice 注释绑定
bind(super.class).annotatedWith(Names.named(path)).to(implementation.class);
另一方面,在我自己的服务 API 中,我想使用 @Named 注释的用户方法注入来定义绑定接收。
@Inject
public void setImplementation(@Named(path) Super<InputType, OutputType> implementation){...}
上述方法的问题是通用的。 super.class 绑定不考虑这些,因此没有找到绑定。
接下来我使用 TypeLiteral 阅读了 Guice 中的泛型绑定。 但是我没有找到让编译器满意的方法。
从 ClassGraph 我收到 ClassInfo。 所以我尝试了以下设置
//class list is the result of ClassGraph
for (Class<?> entry : classList){
Class<? extends Super> implementationClass = (Class<? extends Super> entry;
String value = entry.getAnnotation(Example.class).value();
TypeLiteral<? extends Super> typeLiteral = TypeLiteral.get(implementationClass);
TypeLiteral<?> supertype = typeLiteral.getSupertype(Super.class);
//now the trials start and all are wrong, annotation is left out for now
bind(impelmentationClass.getSuperclass()).to(implementationClass);
bind(impelmentationClass.getSuperclass()).to(entry);
bind(impelmentationClass.getSuperclass()).to(typeLiteral);
bind(supertype).to(implementationClass);
bind(supertype).to(entry);
bind(supertype).to(typeLiteral);
}
我正在尝试的是不可能的,还是我使用 TypeLiteral 错误? 我确实搜索了两天并尝试了更多不同的方法(这只是离家最近的)。 所以我有点陷入僵局,我希望其他人之前遇到过这个问题:)
任何帮助表示赞赏
我只是试了一下(可能不完全相同),但这似乎在我的环境中有效:
public abstract class ChequePrinter<T> implements Printer<T, PrintLayout> {
public abstract print(T cheque);
}
public VoidChequePrinter extends ChequePrinter<VoidCheque> {
public print (VoidCheque cheque);
}
非常简单,除了我打印到 PrintLayout 而不是网络请求,但这无关紧要。 现在对于我的示例,我只是硬编码了 class 定义,而不是从 ClassGraph 中提取它们,但只要:
Class<?> entry is a regular class
应该没问题。 这是我刚刚使用的:
// should be the same as entry
Class<? extends ChequePrinter<?>> clazz = VoidChequePrinter.class;
TypeLiteral typeLiteral = TypeLiteral.get(clazz.getGenericSuperClass());
bind(typeLiteral).annotatedWith(Names.named("Void")).to(clazz);
在我的测试 class VoidChequePrinterTest
我有:
@Inject @Named("Void") ChequePrinter<VoidCheque> printer;
正如我所期望的那样,它可以得到正确的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.