【发布时间】:2018-09-11 15:30:31
【问题描述】:
我正在注入同一接口的多个具体。
我想出了指南“编码”的约定。
我的代码目前吐出
[INFO] App - About to ship. (abc)
[INFO] App - ShipperInterface . (FedExShipper)
[INFO] App - ShipperInterface . (UpsShipper)
[INFO] App - ShipperInterface . (UspsShipper)
所以我有多个“托运人”在我的指尖。
注意方法:
public void ProcessOrder(String preferredShipperAbbreviation, Order ord) {
我正在尝试找出使用(字符串)preferredShipperAbbreviation 选择 3 个具体托运人中的 1 个的最佳方式。
当我在 Guice 注册 3 个混凝土时,有没有办法“命名”它们?
或者从三个中选择一个的最佳方法是什么?
public class ProductionInjectModule extends AbstractModule implements Module {
@Override
protected void configure() {
try {
bind(OrderProcessorInterface.class).toConstructor(OrderProcessorImpl.class.getConstructor(Set.class));
Multibinder<ShipperInterface> multibinder = Multibinder.newSetBinder(binder(), ShipperInterface.class);
multibinder.addBinding().toConstructor(FedExShipper.class.getConstructor(org.apache.commons.logging.Log.class));
multibinder.addBinding().toConstructor(UpsShipper.class.getConstructor(org.apache.commons.logging.Log.class));
multibinder.addBinding().toConstructor(UspsShipper.class.getConstructor(org.apache.commons.logging.Log.class));
} catch (NoSuchMethodException e) {
addError(e);
}
}
}
=============
import java.util.Collection;
import java.util.Set;
import org.apache.commons.logging.Log;
public class OrderProcessorImpl implements OrderProcessorInterface {
private Log logger;
Set<ShipperInterface> shippers;
public OrderProcessorImpl(Log lgr, Set<ShipperInterface> shprs) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
if (null == shprs) {
throw new IllegalArgumentException("ShipperInterface(s) is null");
}
this.logger = lgr;
this.shippers = shprs;
}
public void ProcessOrder(String preferredShipperAbbreviation, Order ord) {
this.logger.info(String.format("About to ship. (%1s)", preferredShipperAbbreviation));
for (ShipperInterface sh : shippers) {
this.logger.info(String.format("ShipperInterface . (%1s)", sh.getClass().getSimpleName()));
}
}
}
=============
public interface OrderProcessorInterface {
void ProcessOrder(String preferredShipperAbbreviation, Order ord);
}
public class FedExShipper implements ShipperInterface {
private Log logger;
public FedExShipper(Log lgr) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
this.logger = lgr;
}
public void ShipOrder(Order ord) {
this.logger.info("I'm shipping the Order with FexEx");
}
}
public class UpsShipper implements ShipperInterface {
private Log logger;
public UpsShipper(Log lgr) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
this.logger = lgr;
}
public void ShipOrder(Order ord) {
this.logger.info("I'm shipping the Order with Ups");
}
}
public class UspsShipper implements ShipperInterface {
private Log logger;
public UspsShipper(Log lgr) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
this.logger = lgr;
}
public void ShipOrder(Order ord) {
this.logger.info("I'm shipping the Order with Usps");
}
}
.......
“主要”方法:
ProductionInjectModule pm = new ProductionInjectModule();
Injector injector = Guice.createInjector(pm);
Order ord = new Order();
OrderProcessorInterface opi = injector.getInstance(OrderProcessorInterface.class);
opi.ProcessOrder("WhatDoIPutHere?", ord);
============ Guice 版本如下:
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.2.0</version>
</dependency>
=================================
我正在尝试这种方式。这和任何方式一样好吗?
最终,在我的“真实”场景中(不是这个虚构的)......我想将“concreteKey”保留为数据库/配置设置。
Order ord = new Order();
OrderProcessorInterface opi = injector.getInstance(OrderProcessorInterface.class);
opi.ProcessOrder(FedExShipper.class.getSimpleName(), ord);
public void ProcessOrder(String preferredShipperAbbreviation, Order ord) {
this.logger.info(String.format("About to ship. (%1s)", preferredShipperAbbreviation));
ShipperInterface foundShipperInterface = this.FindShipperInterface(preferredShipperAbbreviation);
foundShipperInterface.ShipOrder(ord);
}
private ShipperInterface FindShipperInterface(String preferredShipperAbbreviation) {
/* requires java 8 */
ShipperInterface foundShipperInterface = this.shippers
.stream().filter(x -> x.getClass().getSimpleName().equalsIgnoreCase(preferredShipperAbbreviation)).findFirst().orElse(null);
if(null == foundShipperInterface)
{
throw new NullPointerException(String.format("ShipperInterface not found in ShipperInterface collection. ('%1s')", preferredShipperAbbreviation));
}
return foundShipperInterface;
}
============= APPEND ==================
感谢 Jeff B 的回答/cmets,我得到了这个工作。
import java.util.Map;
import java.util.Set;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.google.inject.multibindings.MapBinder;
import com.google.inject.multibindings.Multibinder;
public class ProductionInjectModule extends AbstractModule implements Module {
@Override
protected void configure() {
try {
MapBinder<String, ShipperInterface> mappyBinder = MapBinder.newMapBinder(binder(), String.class, ShipperInterface.class);
mappyBinder.addBinding("myFedExName").toConstructor(FedExShipper.class.getConstructor(org.apache.commons.logging.Log.class));
mappyBinder.addBinding("myUPSName").toConstructor(UpsShipper.class.getConstructor(org.apache.commons.logging.Log.class));
mappyBinder.addBinding("myUSPSName").toConstructor(UspsShipper.class.getConstructor(org.apache.commons.logging.Log.class));
/* below is not needed, but shows what needs to be injected */
java.util.Map<String, javax.inject.Provider<ShipperInterface>> shipperProviderMap;
} catch (NoSuchMethodException e) {
addError(e);
}
}
}
=================
import java.util.Collection;
import java.util.Set;
import org.apache.commons.logging.Log;
public class OrderProcessorImpl implements OrderProcessorInterface {
private Log logger;
private java.util.Map<String, javax.inject.Provider<ShipperInterface>> shipperProviderMap;
public OrderProcessorImpl(Log lgr, java.util.Map<String, javax.inject.Provider<ShipperInterface>> spMap) {
if (null == lgr) {
throw new IllegalArgumentException("Log is null");
}
if (null == spMap) {
throw new IllegalArgumentException("Provider<ShipperInterface> is null");
}
this.logger = lgr;
this.shipperProviderMap = spMap;
}
public void ProcessOrder(String preferredShipperAbbreviation, Order ord) {
this.logger.info(String.format("About to ship. (%1s)", preferredShipperAbbreviation));
ShipperInterface foundShipperInterface = this.FindShipperInterface(preferredShipperAbbreviation);
foundShipperInterface.ShipOrder(ord);
}
private ShipperInterface FindShipperInterface(String preferredShipperAbbreviation) {
ShipperInterface foundShipperInterface = this.shipperProviderMap.get(preferredShipperAbbreviation).get();
if (null == foundShipperInterface) {
throw new NullPointerException(
String.format("ShipperInterface not found in shipperProviderMap. ('%1s')", preferredShipperAbbreviation));
}
return foundShipperInterface;
}
}
=================
“主要”方法
ProductionInjectModule pm = new ProductionInjectModule();
Injector injector = Guice.createInjector(pm);
Order ord = new Order();
OrderProcessorInterface opi = injector.getInstance(OrderProcessorInterface.class);
opi.ProcessOrder("myFedExName", ord); /* now use the "friendly named" strings */
输出:
[INFO] App - About to ship. (myFedExName)
[INFO] App - I'm shipping the Order with FexEx
我的新发布的代码中可能有一些额外的“记录器”注入......但简单的清理就会让它运行。
【问题讨论】:
-
未来的读者,我这里也有一个 Spring IoC / DI 示例:stackoverflow.com/questions/52338322/…
标签: guice