工厂使用 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>>() {}) 一样调用此方法即可。