Я впрыскиваю несколько бетонов одного и того же интерфейса.
Я разобрался с соглашением "Кодируй это" в Руководстве.
Мой код сейчас выплевывает
[INFO] App - About to ship. (abc)
[INFO] App - ShipperInterface . (FedExShipper)
[INFO] App - ShipperInterface . (UpsShipper)
[INFO] App - ShipperInterface . (UspsShipper)
Итак, у меня под рукой несколько «грузоотправителей».
Обратите внимание на метод:
public void ProcessOrder (String предпочитаемыйShipperAbbreviation, Заказ
ord) {
Я пытаюсь выяснить, как лучше всего использовать (String) аббревиатуру предпочитаемой стрелки для выбора 1 из 3 конкретных грузоотправителей.
Есть ли способ "назвать" мои 3 бетона, когда я зарегистрирую их в Guice?
Или как лучше выбрать 1 из трех?
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 ==================
Я получил это на работу благодаря ответу / комментариям Джеффа Б.
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
Возможно, в моем недавно опубликованном коде есть несколько дополнительных «логгеров», но простая очистка запустит его.