如何结合Guice的Assisted Inject、Multibinding与泛型实现对象创建
结合Guice Assisted Inject、Multibinding与泛型实现对象创建与绑定
我来帮你一步步梳理怎么把这三个Guice特性结合起来,完美实现你的原型需求:
1. 调整基类与子类,标记Assisted参数
首先,咱们得明确哪些参数是运行时传入(需要Assisted Inject处理),哪些是Guice自动注入的依赖。这里你的AbstractToCreate的type参数是运行时确定的,所以要用@Assisted标记:
import com.google.inject.assistedinject.Assisted; import javax.inject.Inject; // 泛型基类 public abstract class AbstractToCreate<T extends Type> { public final T type; // 用@Assisted标记运行时传入的参数 protected AbstractToCreate(@Assisted T type) { this.type = type; } // 这里可以添加通用方法... } // 具体子类ToCreate1 public class ToCreate1 extends AbstractToCreate<Type1> { // 示例:Guice自动注入的依赖 private final SomeService someService; // 构造方法:Guice注入的依赖 + Assisted参数 @Inject public ToCreate1(SomeService someService, @Assisted Type1 type) { super(type); this.someService = someService; } // 子类特有方法... } // 具体子类ToCreate2 public class ToCreate2 extends AbstractToCreate<Type2> { private final AnotherService anotherService; @Inject public ToCreate2(AnotherService anotherService, @Assisted Type2 type) { super(type); this.anotherService = anotherService; } // 子类特有方法... }
2. 定义泛型工厂接口
接下来,创建一个泛型工厂接口,用来统一创建AbstractToCreate的实例——这是Assisted Inject的核心入口:
public interface ToCreateFactory<T extends Type> { AbstractToCreate<T> create(T type); }
3. 实现Guice模块:结合Assisted Inject与Multibinding
现在要在Guice模块里完成两件事:
- 用
FactoryModuleBuilder生成工厂的实现类(Assisted Inject的自动实现) - 用
MapBinder把不同类型的工厂绑定到一个Map中,方便后续根据Type类型获取对应工厂
import com.google.inject.AbstractModule; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.multibindings.MapBinder; import com.google.inject.TypeLiteral; public class ToCreateModule extends AbstractModule { @Override protected void configure() { // 为每个子类生成对应的工厂实现 install(new FactoryModuleBuilder() .implement(new TypeLiteral<AbstractToCreate<Type1>>() {}, ToCreate1.class) .build(new TypeLiteral<ToCreateFactory<Type1>>() {})); install(new FactoryModuleBuilder() .implement(new TypeLiteral<AbstractToCreate<Type2>>() {}, ToCreate2.class) .build(new TypeLiteral<ToCreateFactory<Type2>>() {})); // 用Multibinding创建一个Map:Key是Type的Class,Value是对应工厂 MapBinder<Class<? extends Type>, ToCreateFactory<? extends Type>> mapBinder = MapBinder.newMapBinder( binder(), new TypeLiteral<Class<? extends Type>>() {}, new TypeLiteral<ToCreateFactory<? extends Type>>() {}); // 绑定每个Type对应的工厂 mapBinder.addBinding(Type1.class).to(new TypeLiteral<ToCreateFactory<Type1>>() {}); mapBinder.addBinding(Type2.class).to(new TypeLiteral<ToCreateFactory<Type2>>() {}); } }
4. 实际使用:从Map中获取工厂创建对象
最后,你可以在业务代码中注入这个工厂Map,根据传入的Type实例动态获取对应工厂,创建目标对象:
import com.google.inject.Inject; import java.util.Map; public class ObjectCreatorService { private final Map<Class<? extends Type>, ToCreateFactory<? extends Type>> factoryMap; @Inject public ObjectCreatorService(Map<Class<? extends Type>, ToCreateFactory<? extends Type>> factoryMap) { this.factoryMap = factoryMap; } @SuppressWarnings("unchecked") public <T extends Type> AbstractToCreate<T> create(T type) { ToCreateFactory<T> factory = (ToCreateFactory<T>) factoryMap.get(type.getClass()); if (factory == null) { throw new IllegalArgumentException("No factory registered for type: " + type.getClass().getName()); } return factory.create(type); } }
关键注意事项
- TypeLiteral的使用:因为Java泛型擦除,Guice需要明确的类型信息,所以必须用
TypeLiteral来绑定泛型类型,不能直接用Class。 - 泛型转换的SuppressWarnings:这里的类型转换是安全的,因为我们的Map绑定保证了Key和Value的类型匹配,所以可以放心添加这个注解。
- 扩展性:后续新增Type子类和对应的ToCreate子类时,只需要在Module中添加两行代码(工厂实现安装+Map绑定),完全符合开闭原则。
内容的提问来源于stack exchange,提问作者Andrei Koch
相关产品推荐
相关产品推荐

