Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Guice注入通用实现_Java_Ioc Container_Guice_Typeliteral - Fatal编程技术网

Java 使用Guice注入通用实现

Java 使用Guice注入通用实现,java,ioc-container,guice,typeliteral,Java,Ioc Container,Guice,Typeliteral,我希望能够使用Guice注入通用接口的通用实现 public interface Repository<T> { void save(T item); T get(int id); } public MyRepository<T> implements Repository<T> { @Override public void save(T item) { // do saving return item; } @Ov

我希望能够使用Guice注入通用接口的通用实现

public interface Repository<T> {
  void save(T item);
  T get(int id);
}

public MyRepository<T> implements Repository<T> {
  @Override
  public void save(T item) {
    // do saving
    return item;
  }
  @Override
  public T get(int id) {
    // get item and return
  }
}
虽然更可能的用法是注入到另一个类中:

public class ClassThatUsesRepository {
  private Repository<Class1> repository;

  @Inject
  public ClassThatUsesRepository(Repository<Class1> repository) {
    this.repository = repository;
  }
}
使用repository的公共类{
私有存储库;
@注入
使用存储库(存储库)的公共类{
this.repository=存储库;
}
}

为了在Guice中使用泛型,您需要使用类来绑定泛型变量。这是一个示例,说明了Guice喷油器配置的外观:

package your-application.com;

import com.google.inject.AbstractModule;
import com.google.inject.TypeLiteral;

public class MyModule extends AbstractModule {
  @Override
  protected void configure() {
    bind(new TypeLiteral<Repository<Class1>>(){})
      .to(new TypeLiteral<MyRepository<Class1>>(){});
  }
}
package your-application.com;
导入com.google.inject.AbstractModule;
导入com.google.inject.TypeLiteral;
公共类MyModule扩展了AbstractModule{
@凌驾
受保护的void configure(){
绑定(新的TypeLiteral(){})
.to(新的TypeLiteral(){});
}
}

(Repository是泛型接口,MyRepository是泛型实现,Class1是泛型中使用的特定类)。

在运行时没有保留泛型肯定会使最初更难理解这个概念。 无论如何,有理由
新建ArrayList().getClass()
返回
Class
而不是
Class
,尽管将其强制转换到
Class是安全的,但您可以使用
@ImplementedBy
注释来让Guice为您生成通用绑定:

@ImplementedBy(MyRepository.class)
interface Repository<T> { ... }

class MyRepository<T> implements Repository<T> { ... }
这通常不是问题,但这意味着
MyRepository
无法在运行时注入
TypeLiteral
来找出自己的类型,这在这种情况下尤其有用。除此之外,据我所知,这很好用


(如果有人想解决这个问题,我敢肯定这只需要一些额外的计算来从源代码键填充目标类型参数。)

有些关联,希望有人会发现这很有用。在某些情况下,特别是当您拥有想要泛化的java.lang.Class实例时,可以通过扩展ParameterizeType类在运行时强制注入

在下面的解决方案中,工厂方法创建一个通用的集合<?给定类对象的实例,扩展Number>映射

Example.java:

@SuppressWarnings("unchecked")
public class Example<K extends Number> {

  Injector injector = ...

  public Set<K> foo(Class<K> klass) {
    CompositeType typeLiteral = new CompositeType(Set.class, klass);
    Set<K> set = (Set<K>) injector.getInstance(Key.get(typeLiteral));
    return set;
  }

  public <V> Map<K,V> bar(Class<K> keyClass, Class<V> valueClass) {
    CompositeType typeLiteral = new CompositeType(Map.class, keyClass, valueClass);
    Map<K,V> collection = (Map<K,V>) injector.getInstance(Key.get(typeLiteral));
    return collection;
  }
}
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;

public class CompositeType implements ParameterizedType {

  private final String typeName;
  private final Class<?> baseClass;
  private final Type[] genericClass;

  public CompositeType(Class<?> baseClass, Class<?>... genericClasses) {
    this.baseClass = baseClass;
    this.genericClass = genericClasses;
    List<String> generics = ((List<Class<?>>)Arrays.asList(genericClasses))
            .stream()
            .map(Class::getName)
            .collect(Collectors.toList());
    String genericTypeString = StringUtils.join(generics, ",");
    this.typeName = baseClass.getName() + "<" + genericTypeString + ">";
  }

  @Override
  public String getTypeName() {
    return typeName;
  }

  @Override
  public Type[] getActualTypeArguments() {
    return genericClass;
  }

  @Override
  public Type getRawType() {
    return baseClass;
  }

  @Override
  public Type getOwnerType() {
    return null;
  }
}
@SuppressWarnings(“未选中”)
公开课范例{
喷油器喷油器=。。。
公共设置foo(klass类){
CompositeType typeLiteral=新的CompositeType(Set.class,klass);
Set=(Set)injector.getInstance(Key.get(typeLiteral));
返回集;
}
公共地图栏(Class keyClass、Class valueClass){
CompositeType typeLiteral=新的CompositeType(Map.class、keyClass、valueClass);
映射集合=(Map)injector.getInstance(Key.get(typeLiteral));
回收;
}
}
CompositeType.java:

@SuppressWarnings("unchecked")
public class Example<K extends Number> {

  Injector injector = ...

  public Set<K> foo(Class<K> klass) {
    CompositeType typeLiteral = new CompositeType(Set.class, klass);
    Set<K> set = (Set<K>) injector.getInstance(Key.get(typeLiteral));
    return set;
  }

  public <V> Map<K,V> bar(Class<K> keyClass, Class<V> valueClass) {
    CompositeType typeLiteral = new CompositeType(Map.class, keyClass, valueClass);
    Map<K,V> collection = (Map<K,V>) injector.getInstance(Key.get(typeLiteral));
    return collection;
  }
}
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;

public class CompositeType implements ParameterizedType {

  private final String typeName;
  private final Class<?> baseClass;
  private final Type[] genericClass;

  public CompositeType(Class<?> baseClass, Class<?>... genericClasses) {
    this.baseClass = baseClass;
    this.genericClass = genericClasses;
    List<String> generics = ((List<Class<?>>)Arrays.asList(genericClasses))
            .stream()
            .map(Class::getName)
            .collect(Collectors.toList());
    String genericTypeString = StringUtils.join(generics, ",");
    this.typeName = baseClass.getName() + "<" + genericTypeString + ">";
  }

  @Override
  public String getTypeName() {
    return typeName;
  }

  @Override
  public Type[] getActualTypeArguments() {
    return genericClass;
  }

  @Override
  public Type getRawType() {
    return baseClass;
  }

  @Override
  public Type getOwnerType() {
    return null;
  }
}
import java.lang.reflect.ParameterizedType;
导入java.lang.reflect.Type;
导入java.util.array;
导入java.util.List;
导入java.util.stream.collector;
导入org.apache.commons.lang.StringUtils;
公共类CompositeType实现参数化类型{
私有最终字符串类型名;
私有最终类基类;
私有最终类型[]genericClass;
公共复合类型(类基类、类…泛型类){
this.baseClass=基类;
this.genericClass=genericClass;

List generics=((列表能否添加一段代码,说明您希望如何使用它?我同意您的意见,我也想做同样的事情。每个人都应该有这个问题。一定有什么他们没有告诉我们的。)我也想知道解决方案,我对C#一无所知,但显然C#方式更加现代。仍然没有可用的解决方案?对所有可能的泛型值重复绑定是浪费时间。当然,在某些特殊情况下,您可能确实需要不同的实现,但它不应该是默认的。我就是这样做的。什么我希望做的是消除注册每个实现(MyRepository、MyRepository等)的需要。这就是温莎示例所做的。很抱歉,我应该更仔细地阅读您的问题。我自己一直在研究这种类型的Guice泛型用法,但我也无法解决它。我想解决它的一种方法是扩展Guice并编写您自己的模块(helper).使用Java反射API,您可以找到所有注入变量并将其绑定。
    @Override
    protected void configure() {
        bind(List<String>.class).to(LinkedList<String>.class); <-- *Not Happening*
    }
    @Override
    protected void configure() {
        bind(new TypeLiteral<List<String>>(){}).to(new TypeLiteral<LinkedList<String>>(){});
    }
@ImplementedBy(MyRepository.class)
interface Repository<T> { ... }

class MyRepository<T> implements Repository<T> { ... }
    Injector injector = Guice.createInjector();
    System.out.println(injector.getBinding(new Key<Repository<String>>(){}));
    System.out.println(injector.getBinding(new Key<Repository<Integer>>(){}));
LinkedKeyBinding{key=Key[type=Repository<java.lang.String>, annotation=[none]], source=interface Repository, scope=Scopes.NO_SCOPE, target=Key[type=MyRepository, annotation=[none]]}
LinkedKeyBinding{key=Key[type=Repository<java.lang.Integer>, annotation=[none]], source=interface Repository, scope=Scopes.NO_SCOPE, target=Key[type=MyRepository, annotation=[none]]}
@SuppressWarnings("unchecked")
public class Example<K extends Number> {

  Injector injector = ...

  public Set<K> foo(Class<K> klass) {
    CompositeType typeLiteral = new CompositeType(Set.class, klass);
    Set<K> set = (Set<K>) injector.getInstance(Key.get(typeLiteral));
    return set;
  }

  public <V> Map<K,V> bar(Class<K> keyClass, Class<V> valueClass) {
    CompositeType typeLiteral = new CompositeType(Map.class, keyClass, valueClass);
    Map<K,V> collection = (Map<K,V>) injector.getInstance(Key.get(typeLiteral));
    return collection;
  }
}
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;

public class CompositeType implements ParameterizedType {

  private final String typeName;
  private final Class<?> baseClass;
  private final Type[] genericClass;

  public CompositeType(Class<?> baseClass, Class<?>... genericClasses) {
    this.baseClass = baseClass;
    this.genericClass = genericClasses;
    List<String> generics = ((List<Class<?>>)Arrays.asList(genericClasses))
            .stream()
            .map(Class::getName)
            .collect(Collectors.toList());
    String genericTypeString = StringUtils.join(generics, ",");
    this.typeName = baseClass.getName() + "<" + genericTypeString + ">";
  }

  @Override
  public String getTypeName() {
    return typeName;
  }

  @Override
  public Type[] getActualTypeArguments() {
    return genericClass;
  }

  @Override
  public Type getRawType() {
    return baseClass;
  }

  @Override
  public Type getOwnerType() {
    return null;
  }
}