Spring DI (Beans) with multiple concretes…picking one of them

痴心易碎 提交于 2019-11-28 14:41:55

I think I have something that works:

beans.xml (note the "util" extras in the namespace declares)

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util-2.5.xsd">


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


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

    <bean id="upsShipperBean"
        class="com.me.shipping.UpsShipper">
        <constructor-arg ref="theLoggerBean"></constructor-arg>
    </bean>

    <bean id="uspsShipperBean"
        class="com.me.shipping.UspsShipper">
        <constructor-arg ref="theLoggerBean"></constructor-arg>
    </bean>

    <util:map id="shipperInterfaceMap" key-type="java.lang.String"
        value-type="com.me.shipping.interfaces.ShipperInterface">
        <entry key="fedexFriendlyName" value-ref="fedExShipperBean" />
        <entry key="upsFriendlyName" value-ref="upsShipperBean" />
        <entry key="uspsFriendlyName" value-ref="uspsShipperBean" />
    </util:map>

    <bean id="orderProcessorImplBean"
        class="com.me.shipping.OrderProcessorImpl">
        <constructor-arg ref="theLoggerBean"></constructor-arg>
        <constructor-arg ref="shipperInterfaceMap"></constructor-arg>
    </bean>


</beans>

and java

 package com.me.shipping;


import java.util.Collection;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;

import com.me.shipping.interfaces.OrderProcessorInterface;
import com.me.shipping.interfaces.ShipperInterface;
import com.me.Models.Order;


public class OrderProcessorImpl implements OrderProcessorInterface {

  private Log logger;
  private java.util.Map<String, ShipperInterface> shipperInterfaceMap;


  public OrderProcessorImpl(Log lgr, java.util.Map<String, ShipperInterface> siMap) {

    if (null == lgr) {
      throw new IllegalArgumentException("Log is null");
    }

    if (null == siMap) {
      throw new IllegalArgumentException("Map<String, ShipperInterface> is null");
    }

    this.logger = lgr;
    this.shipperInterfaceMap = siMap;
  }

  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 friendlyName)
    {
        ShipperInterface returnItem = null;
        if (null != this.shipperInterfaceMap)
        {
            returnItem = this.shipperInterfaceMap.entrySet().stream()
                    .filter(e -> e.getKey().equalsIgnoreCase(friendlyName))
                      .map(Map.Entry::getValue)
                      .findFirst()
                      .orElse(null);
        }

        if (null == returnItem)
        {
            throw new NullPointerException(String.format("shipperProviderMap did not contain expected item. (Key='%s')", friendlyName));
        }

        return returnItem;
    }
}

and "main" method

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

        Order ord = new Order();
        OrderProcessorInterface opi = context.getBean(OrderProcessorImpl.class);
        opi.ProcessOrder("fedexFriendlyName", ord);
jbppsu

Something like this should work. This uses @Autowired and not xml configuration:

@org.springframework.stereotype.Service
public class OrderProcessorImpl implements OrderProcessorInterface {

    private List<ShipperInterface> shipperProviders;

    private Map<String, ShipperInterface> shipperProvidersMap = new HashMap<>();

    @Autowired
    public void setShipperProviders(List<ShipperInterface> shipperProviders) {
        this.shipperProviders= shipperProviders;

        this.shipperProviders.stream().forEach(p->shipperProvidersMap .put(/* your code for getting the key */, p));
    }

Gradle dependency hint:

compile group: 'org.springframework', name: 'spring-context', version: '5.1.9.RELEASE'
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!