工厂使用 CDI 返回类型捕获而不是具体类型
Factory using CDI returning capture of type instead of concrete type
我想创建一个使用 CDI 获取所有可用处理器的处理器工厂。工厂应该 select 基于某些参数的所需处理器。所以我有我的参数:
public abstract class Parameter { }
@CorrespondingProcessor(type = StringProcessor.class)
public class StringParameter extends Parameter { }
@CorrespondingProcessor(type = FileProcessor.class)
public class FileParameter extends Parameter { }
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CorrespondingProcessor {
Class<? extends Processor<? extends Parameter>> type();
}
每个参数都有一个处理器:
public interface Processor<T extends Parameter> {
String work(T parameter);
}
public class StringProcessor implements Processor<StringParameter> {
@Override
public String work(StringParameter parameter) {
return "string";
}
}
public class FileProcessor implements Processor<FileParameter> {
@Override
public String work(FileParameter parameter) {
return "file";
}
}
基本上我的工厂是这样的:
public class ProcessorFactory {
private final Instance<Processor<? extends Parameter>> processors;
@Inject
public ProcessorFactory(@Any Instance<Processor<? extends Parameter>> processors) {
this.processors = processors;
}
public <T extends Parameter> Processor<T> getProcessor(T parameter) {
CorrespondingProcessor annotation = parameter.getClass().getAnnotation(CorrespondingProcessor.class);
CorrespondingProcessorLiteral correspondingProcessorLiteral = new CorrespondingProcessorLiteral(annotation.type());
Class<? extends Processor<? extends Parameter>> type = correspondingProcessorLiteral.type();
Processor<? extends Parameter> processor = processors.select(type).get();
return processor;
}
private class CorrespondingProcessorLiteral extends AnnotationLiteral<CorrespondingProcessor> implements CorrespondingProcessor {
private final Class<? extends Processor<? extends Parameter>> type;
public CorrespondingProcessorLiteral(Class<? extends Processor<? extends Parameter>> type) {
this.type = type;
}
@Override
public Class<? extends Processor<? extends Parameter>> type() {
return type;
}
}
}
这不会编译,因为 getProcessor
方法定义的 return 类型不同于 returned processor
变量。编译器不知道 selected 处理器是否是 T 的处理器。在这一点上我很挣扎。有没有办法让它工作?我如何强制 selected 处理器是 T 的处理器?或者这种方法首先是错误的?
我不想自己注入所有可用的处理器。因为这意味着,我每次添加新处理器时都必须更改工厂。
解决方案是使用 TypeLiteral
而不是 AnnotationLiteral
。但正如 中所讨论的,必须在编译时提供实际类型。
processors.select(new TypeLiteral<Processor<T>>() {}).get()
这将不起作用,因为类型 T 由于类型擦除而被擦除。
所以getProcessor
-方法必须改成:
public <T extends Parameter> Processor<T> getProcessor(TypeLiteral<Processor<T>> selector) {
return processors.select(selctor).get();
}
像 factory.getProcessor(new TypeLiteral<Processor<StringParameter>>() {})
一样调用此方法即可。
我想创建一个使用 CDI 获取所有可用处理器的处理器工厂。工厂应该 select 基于某些参数的所需处理器。所以我有我的参数:
public abstract class Parameter { }
@CorrespondingProcessor(type = StringProcessor.class)
public class StringParameter extends Parameter { }
@CorrespondingProcessor(type = FileProcessor.class)
public class FileParameter extends Parameter { }
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CorrespondingProcessor {
Class<? extends Processor<? extends Parameter>> type();
}
每个参数都有一个处理器:
public interface Processor<T extends Parameter> {
String work(T parameter);
}
public class StringProcessor implements Processor<StringParameter> {
@Override
public String work(StringParameter parameter) {
return "string";
}
}
public class FileProcessor implements Processor<FileParameter> {
@Override
public String work(FileParameter parameter) {
return "file";
}
}
基本上我的工厂是这样的:
public class ProcessorFactory {
private final Instance<Processor<? extends Parameter>> processors;
@Inject
public ProcessorFactory(@Any Instance<Processor<? extends Parameter>> processors) {
this.processors = processors;
}
public <T extends Parameter> Processor<T> getProcessor(T parameter) {
CorrespondingProcessor annotation = parameter.getClass().getAnnotation(CorrespondingProcessor.class);
CorrespondingProcessorLiteral correspondingProcessorLiteral = new CorrespondingProcessorLiteral(annotation.type());
Class<? extends Processor<? extends Parameter>> type = correspondingProcessorLiteral.type();
Processor<? extends Parameter> processor = processors.select(type).get();
return processor;
}
private class CorrespondingProcessorLiteral extends AnnotationLiteral<CorrespondingProcessor> implements CorrespondingProcessor {
private final Class<? extends Processor<? extends Parameter>> type;
public CorrespondingProcessorLiteral(Class<? extends Processor<? extends Parameter>> type) {
this.type = type;
}
@Override
public Class<? extends Processor<? extends Parameter>> type() {
return type;
}
}
}
这不会编译,因为 getProcessor
方法定义的 return 类型不同于 returned processor
变量。编译器不知道 selected 处理器是否是 T 的处理器。在这一点上我很挣扎。有没有办法让它工作?我如何强制 selected 处理器是 T 的处理器?或者这种方法首先是错误的?
我不想自己注入所有可用的处理器。因为这意味着,我每次添加新处理器时都必须更改工厂。
解决方案是使用 TypeLiteral
而不是 AnnotationLiteral
。但正如
processors.select(new TypeLiteral<Processor<T>>() {}).get()
这将不起作用,因为类型 T 由于类型擦除而被擦除。
所以getProcessor
-方法必须改成:
public <T extends Parameter> Processor<T> getProcessor(TypeLiteral<Processor<T>> selector) {
return processors.select(selctor).get();
}
像 factory.getProcessor(new TypeLiteral<Processor<StringParameter>>() {})
一样调用此方法即可。