当前位置: 首页 > 知识库问答 >
问题:

SpringDI(豆类)与多个混凝土...选择其中之一

岳允晨
2023-03-14

我这里也有类似的问题

有多重混凝土的Guice……挑其中一个

为Guice提供解决方案。

但是我有一个使用Spring di(bean)的不同项目,但是有同样的问题。

我有一个包含N个混凝土的接口。(此处为3)

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

........

然后我有一个班级需要了解所有三个混凝土。

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

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

基本上,我想调用这个方法,传入一个字符串参数,让它为我选择具体的。(如果是我的真实代码,这是通过一个数据库值,但是对于演示代码,这已经足够好了)

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 */

我的Spring配置是通过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>

所以我想用xml配置3个具体的东西。

然后把它们注入课堂。

但是在我有“如何在这里处理N个船舶接口??”的地方,我不知道该怎么办。

JSR 330的实现是首选,但需要任何东西。

谢谢。

注意,在另一个问题(Guice问题)中,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()));
    }

  }
}

共有2个答案

徐学潞
2023-03-14

我想我有一些有用的东西:

beans.xml(注意命名空间中的util附加声明)

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

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

和“主要”方法

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

        Order ord = new Order();
        OrderProcessorInterface opi = context.getBean(OrderProcessorImpl.class);
        opi.ProcessOrder("fedexFriendlyName", ord);
邢昊焜
2023-03-14

像这样的东西应该可以工作。这使用@Autowired而不是 xml 配置:

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

渐变依赖提示:

compile group: 'org.springframework', name: 'spring-context', version: '5.1.9.RELEASE'
 类似资料:
  • 我在一个Java项目中工作,并开始使用Spock框架在Groovy中编写单元测试。但我对Spock的嘲讽功能有意见,希望有人能找出我做错了什么。 然后,我使用Spock在Groovy中编写了以下单元测试: 此测试失败如下: dofoo调用getfoo:21没有可用的foo

  • 虽然下面的代码是一个早期的原型,对于我在这个阶段如何实现协议缓冲区不必太认真,但我无法理解rust编译器给我带来的错误消息指的是什么。 src\main。rs:89:9:89:36错误:解决的类型不匹配

  • 问题内容: 我的外观很好,似乎无法找出如何在一个jQuery选择器语句中选择与某些类匹配的所有元素,例如: 关于如何实现这一目标的任何想法?唯一的其他选择是 但是我正在使用很多类来执行此操作,因此它需要很多代码。 问题答案: 这应该工作: 您必须在$()的第一个参数中全部添加多个选择器,否则,您将为jQuery提供要在其中搜索的上下文,这不是您想要的。 这与您在CSS中所做的相同。

  • 我有一个样式规则,当一个标记有两个类时,我想应用于它。在没有JavaScript的情况下,有什么方法可以执行此操作吗?换句话说: 只有在同时应用了和类时,我才要应用我的样式规则。

  • 问题内容: 所以,我想用香草JS做的事情很简单,但是我使用的是AngularJS,我想知道如何在框架内以最佳方式做到这一点。我想在多个选择框中更新所选的选项。我不想添加或删除任何选项。这是我的HTML外观: 使用以下数组,我想以编程方式从此列表中选择/取消选择选项: 当我在范围中设置此数组时,我希望选择框取消选择不是蓝色或红色的任何内容,然后选择蓝色和红色。我在Google网上论坛上看到的标准回复

  • 我有一个问题与生命周期参数的结构。我不能100%确定如何描述这个问题,但是我创建了一个显示编译时错误的简单案例。 我得到的错误是 我尝试了很多变体,只是无法编译这个东西。我在这里找到了另一个帖子(如何修复:预期的具体寿命,但找到了绑定的寿命参数),但似乎绕过了问题,而不是解决它。我真的不明白为什么这个问题会出现。该 有什么想法吗?谢谢你的帮助。