将通用抽象超级 class 绑定到多个非通用实现 classes

Binding a generic abstract super class to multiple non-generic implementation classes

我相信我的设置有点不合常规,所以解释会更长一些。 我有一个抽象的超级class,方法是

public abstract T execute(P parameters);

我有一组实现 classes 扩展它,并在扩展语句中分配各个类型。这意味着实现不是通用的。

我通过注解@Example 获取了所有的实现。我使用 ClassGraph 提取有关这些 classes 的信息。通过它,我不仅获得了实现,还获得了具有定义类型的正确 superclass。

但是我现在无法使用 Guice bind().to();

提供更多背景知识...

我有一组实现 classes,它与外部 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 绑定不考虑这些,因此未找到绑定。

接下来我阅读了 Guice 中的泛型绑定和 TypeLiteral。但是我没有找到让编译器满意的方法。

我从 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;

如我所料,结果正确。