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

后端 未结 2 728
小鲜肉
小鲜肉 2020-12-12 06:24

I have a similar question here

Guice with multiple concretes......picking one of them

with a solution for Guice.

But I have a different project usin

相关标签:
2条回答
  • 2020-12-12 06:51

    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);
    
    0 讨论(0)
  • 2020-12-12 06:55

    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'
    
    0 讨论(0)
提交回复
热议问题