Spring DI (Frijoles) con múltiples hormigones ... eligiendo uno de ellos

Tengo una pregunta similar aquí

Guice con múltiples hormigones ...... eligiendo uno de ellos

con una solución para Guice.

Pero tengo un proyecto diferente usando spring di (beans), pero con el mismo tipo de problema.

Tengo una interfaz con N número de hormigones. (3 aquí)

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");
  }
}

........

Entonces tengo una clase que necesita saber sobre TODOS LOS TRES hormigones.

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;
  }
}

=============

Básicamente, quiero llamar al método, pasar un argumento de cadena y hacer que elija el concreto para mí. (si mi código real, esto es a través de un valor de base de datos, pero para el código de demostración, esto es lo suficientemente bueno)

Order ord = new Order();
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
BeanFactory factory = context;

OrderProcessorInterface opi = context.getBean(OrderProcessorImpl.class);
opi.ProcessOrder("myFedExName", ord); /* friendlyName would be nice, but fully qualified concrete name also assceptable */

Mi configuración de primavera es a través de xml:

 <bean id="theLoggerBean"
       class="org.apache.commons.logging.impl.Log4JLogger">
       <constructor-arg value="log" />
 </bean>    



<bean id="fedExBean"
    class="com.me.FedExShipper">
    <constructor-arg ref="theLoggerBean"></constructor-arg>
</bean>


<bean id="uspsExBean"
    class="com.me.FedExShipper">
    <constructor-arg ref="theLoggerBean"></constructor-arg>
</bean>


<bean id="upsExBean"
    class="com.me.FedExShipper">
    <constructor-arg ref="theLoggerBean"></constructor-arg>
</bean>

..........

================================

<bean id="OrderProcessorImplBean"
    class="com.me.OrderProcessorImpl">

    <constructor-arg ref="theLoggerBean"></constructor-arg>

    <constructor-arg ref="How do I do N Number of ShipperInterfaces Here ??"></constructor-arg>

</bean>

Así que quiero configurar xml los 3 hormigones.

Y luego inyectarlos en la clase.

Pero donde tengo "¿Cómo hago N Número de interfaces de remitente aquí?", No tengo idea de qué hacer.

e prefiere la implementación de @JSR 330, pero tomará cualquier cosa.

GRACIA

Nota, en la otra pregunta (la de Guice), esta también era una posibilidad para el constructor del OrderProcessor:

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()));
    }

  }
}

Respuestas a la pregunta(2)

Su respuesta a la pregunta