Java 使用Guice注入通用实现
我希望能够使用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
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;
}
}