如何使Guice MapBinder真正实现类型安全



以下是我的StatusMapper界面的样子:

public interface StatusMapper<T extends Throwable> {
    Status map(final T exception);
}

这是我的MapBinder:

    TypeLiteral<Class<? extends Throwable>> exceptionType = new TypeLiteral<Class<? extends Throwable>>() { };
    TypeLiteral<StatusMapper<? extends Throwable>> mapperType = new TypeLiteral<StatusMapper<? extends Throwable>>() { };
    MapBinder<Class<? extends Throwable>, StatusMapper<? extends Throwable>> exceptionBinder = MapBinder.newMapBinder(binder(), exceptionType, mapperType);
    exceptionBinder.addBinding(IOException.class).to(IOExceptionMapper.class);
    exceptionBinder.addBinding(SQLException.class).to(SQLExceptionMapper.class);
    ...

这就是其中一个ExceptionMapper的样子:(简化)

public class IOExceptionMapper implements StatusMapper<IOException> {
    @SuppressWarnings("unused")
    private static final Logger logger = LoggerFactory.getLogger(IOExceptionMapper.class);
    @Override
    public Status map(final IOException exception) {
        return new Status(100);
    }
}

到目前为止,这很好,但我必须注意IOException绑定到IOExceptionMapper。如果我绑定exceptionBinder.addBinding(IOException.class).to(SQLExceptionMapper.class);,类型检查器(编译器)不会抱怨,但它会破坏整个应用程序——有什么提示吗?

[更新]根据The111的回答,我创建了ExceptionBinder

public class ExceptionBinder {
    private final MapBinder<Class<? extends Throwable>, StatusMapper<? extends Throwable>> exceptionBinder;
    public ExceptionBinder(final Binder binder) {
        final TypeLiteral<Class<? extends Throwable>> exceptionType;
        final TypeLiteral<StatusMapper<? extends Throwable>> mapperType;
        exceptionType = new TypeLiteral<Class<? extends Throwable>>() {};
        mapperType = new TypeLiteral<StatusMapper<? extends Throwable>>() {};
        exceptionBinder = MapBinder.newMapBinder(binder, exceptionType, mapperType);
    }
    public <T extends Throwable> void bind(Class<T> exceptionClass, Class<? extends StatusMapper<T>> mapperClass) {
        exceptionBinder.addBinding(exceptionClass).to(mapperClass);
    }
}

这就是我的Guice模块的样子:

final ExceptionBinder eb = new ExceptionBinder(binder());
eb.bind(IOException.class,IOExceptionMapper.class);
eb.bind(SQLException.class,SQLExceptionMapper.class);

您的问题似乎与此有关:Java映射,其值受键';s型参数

如果您将Guice MapBinder封装在自己的TypeSafeMapBinder中,并为该类提供一个方法,如:

void addToBinder(Class<T extends Throwable> eClass,
                 Class<? extends StatusMapper<T>> mClass) {
    getWrappedBinder().addBinding(eClass, mClass);
}

我还没有测试过,所以请告诉我你的结果。

最新更新