【问题标题】:With Guice how to bind multiple instances of a parameterized class when implementation use generics?当实现使用泛型时,如何使用 Guice 绑定参数化类的多个实例?
【发布时间】:2012-01-04 16:08:41
【问题描述】:

在这种情况下,我试图避免使用我自己的工厂,但我找不到使用 Guice 的方法,可能是因为我是使用 guice 的新手;)

我有这个接口可以将 E 型转换为 D 型:

public interface SerializationProvider<E extends ValueEntity, D extends ModelDTO> {

D serialize(E entity) throws MappingSerializationException;

}

现在使用 Dozer 和一些反射,我可以使用一个独特的 Default 类来实现它,如下所示:

public class DefaultSerializationProvider<E extends ValueEntity, D extends ModelDTO>          implements
    SerializationProvider<E, D> {
private Mapper mapper;
private Class<D> dtoClass;

@Inject
public DefaultSerializationProvider(Class<D> dtoClass){
    this.dtoClass=dtoClass;
}

@Override
public D serialize(E entity) throws MappingSerializationException {
    D result=this.getNewDTOInstance();
    this.mapper.map(entity, result);
    return result;
}

protected D getNewDTOInstance() throws MappingSerializationException {
    try{
        D result=this.dtoClass.newInstance();
        return result;
    }catch(InvocationException ie){
        throw new MappingSerializationException(ie);
    }catch(IllegalAccessException iae){
        throw new MappingSerializationException(iae);
    }catch(InstantiationException iie){
        throw new MappingSerializationException(iie);
    }
}

@Inject
public void setMapper(Mapper mapper) {
    this.mapper = mapper;
}

}

请注意,我注入了 Mapper。

现在的问题是如何绑定它以便根据不同的对 E、D 提供 DefaultSerializationProvider 的不同实例 我要避免的是创建空洞的子类,其唯一目的是定义泛型。

在纯 Java 中,我知道我可以提供一个工厂来提供这种实例,例如:

public interface SerializationProviderFactory {

public <E extends ValueEntity, D extends ModelDTO> SerializationProvider<E,D> get(Class<E> entityType, Class<D> dtoType);

}

一个非常简单的实现是:

public class DefaultSerializationProviderFactory implements
    SerializationProviderFactory {
public static final DefaultSerializationProviderFactory INSTANCE=new  DefaultSerializationProviderFactory();

@Override
public <E extends ValueEntity, D extends ModelDTO> SerializationProvider<E, D> get(
        Class<E> entityType, Class<D> dtoType) {
    return new DefaultSerializationProvider<E, D>(dtoType);
}

}

现在的问题是如何使用 Guice 实现这种工厂? 或者有更好的方法吗?

工厂的一个简单用例是:

public MessureUnitDTO serializeUnit(MessureUnit unit){
    SerializationProviderFactory factory=DefaultSerializationProviderFactory.INSTANCE;
    SerializationProvider<MessureUnit, MessureUnitDTO> provider=factory.get(MessureUnit.class, MessureUnitDTO.class);
    return provider.serialize(unit);

}

提前致谢, 丹尼尔

【问题讨论】:

    标签: java inversion-of-control guice factories


    【解决方案1】:

    据我所知,没有办法为所有可能的类型参数绑定DefaultSerializationProvider。但是,如果您可以枚举所有需要转换的类型参数,则可以使用这样的绑定:

    bind(new TypeLiteral<SerializationProvider<MessureUnit, MessureUnitDTO>>() {})
        .toInstance(new DefaultSerializationProvider<MessureUnit, MessureUnitDTO>(MessureUnitDTO.class));
    

    如果您愿意,可以通过将类型文字注入DefaultSerializationProvider 来避免使用toInstance

    @Inject public DefaultSerializationProvider(TypeLiteral<D> dtoType) {
      this.dtoClass = (Class<D>) dtoType.getRawType();
    }
    

    然后你可以使用这样的绑定:

    bind(new TypeLiteral<SerializationProvider<MessureUnit, MessureUnitDTO>>() {})
        .to(new TypeLiteral<DefaultSerializationProvider<MessureUnit, MessureUnitDTO>>() {});
    

    【讨论】:

      【解决方案2】:

      您可以使用Key.get(TypeLiteral&lt;T&gt; typeLiteral&gt; 实现对实例的参数化绑定。

      MyClass<MyType> myClassInstanceOfMyType = new MyClass<MyType>();    
      bind(Key.get(new TypeLiteral<MyClass<MyType>>(){})).toInstance(myClassInstanceOfMyType);
      

      然后在构造函数或基于成员的注入中使用 as:

      class MyOtherClass {
      
        @Inject
        MyOtherClass(MyClass<MyType> myClass){}
        //stuff
      }
      

      class MyOtherClass {
      
       @Inject
       MyClass<MyType> myClass;
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-27
        • 2017-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-02
        • 1970-01-01
        • 2023-03-03
        相关资源
        最近更新 更多