Java Spring-如何在依赖bean中选择属性?

Java Spring-如何在依赖bean中选择属性?,java,spring,inversion-of-control,Java,Spring,Inversion Of Control,假设我的SpringXML中有以下bean: <bean id="mqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory"> <property name="hostName" value="${host}"/> <property name="port" value="${mq.port}"/> </bean> <bean id="jmsQue

假设我的SpringXML中有以下bean:

<bean id="mqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
    <property name="hostName" value="${host}"/>
    <property name="port" value="${mq.port}"/>
</bean>

<bean id="jmsQueueConnectionFactory"
      class="org.springframework.jms.connection.SingleConnectionFactory">
    <property name="targetConnectionFactory" ref="mqConnectionFactory"/>
</bean>

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="jmsQueueConnectionFactory"/>
</bean>
更新: 我可以创建以下配置:

<bean id="mqConnectionFactory1" class="com.ibm.mq.jms.MQQueueConnectionFactory">
    <property name="hostName" value="${host1}"/>
    <property name="port" value="${mq.port}"/>
</bean>

<bean id="mqConnectionFactory2" class="com.ibm.mq.jms.MQQueueConnectionFactory">
    <property name="hostName" value="${host2}"/>
    <property name="port" value="${mq.port}"/>
</bean>

<bean id="jmsQueueConnectionFactory1"
      class="org.springframework.jms.connection.SingleConnectionFactory">
    <property name="targetConnectionFactory" ref="mqConnectionFactory1"/>
</bean>

<bean id="jmsQueueConnectionFactory2"
      class="org.springframework.jms.connection.SingleConnectionFactory">
    <property name="targetConnectionFactory" ref="mqConnectionFactory2"/>
</bean>

<bean id="jmsTemplate1" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="jmsQueueConnectionFactory1"/>
</bean>

<bean id="jmsTemplate2" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="jmsQueueConnectionFactory2"/>
</bean>
这似乎是错误和复杂的。问题是减少此配置并将主机作为参数传递。换句话说,我想告诉Spring:“创建我的jmsTemplate并将connectionFactory的属性host设置为这个值。”

我就是这么做的:

我有不同的属性文件,其中包含不同环境(如本地、开发和生产)的连接信息

  • db.local.properties
  • db.dev.properties
  • db.prod.properties
通过设置环境变量运行应用程序时,我仅使用了以下属性文件之一:

<bean id="dbPlaceholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location" value="classpath:db.${db.environment:dev}.properties"/>
</bean>
因为我使用的是Tomcat,所以我在
sentenv.sh
中定义了该变量,但我确信其他应用程序服务器也提供了类似的机制

然后我使用属性文件提供的参数编写代码

@Value("${db.url}")
private String databaseUrl;
@Value("${db.userName}")
private String userName;
@Value("${db.password}")
private String password;
我就是这么做的:

我有不同的属性文件,其中包含不同环境(如本地、开发和生产)的连接信息

  • db.local.properties
  • db.dev.properties
  • db.prod.properties
通过设置环境变量运行应用程序时,我仅使用了以下属性文件之一:

<bean id="dbPlaceholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location" value="classpath:db.${db.environment:dev}.properties"/>
</bean>
因为我使用的是Tomcat,所以我在
sentenv.sh
中定义了该变量,但我确信其他应用程序服务器也提供了类似的机制

然后我使用属性文件提供的参数编写代码

@Value("${db.url}")
private String databaseUrl;
@Value("${db.userName}")
private String userName;
@Value("${db.password}")
private String password;

您的方案的问题是JMS连接器是一个单例,这意味着它在应用程序中的所有对象/线程之间共享。因此,在一个对象/线程中更改其主机配置将导致使用它的其他对象/线程出现问题

我的建议是使用Springbean“parent”(参见*1)来定义到每个适用主机的不同jms连接,然后使用@Resource而不是autowire(或@autowire@Qualifier组合来强制bean)进行连接参见*2)

编辑:另一个可能的解决方案是使用FactoryBean,尽管我对语法不是100%确定

*一,


*2

您的建议的问题是JMS连接器是一个单例,这意味着它在应用程序中的所有对象/线程之间共享。因此,在一个对象/线程中更改其主机配置将导致使用它的其他对象/线程出现问题

我的建议是使用Springbean“parent”(参见*1)来定义到每个适用主机的不同jms连接,然后使用@Resource而不是autowire(或@autowire@Qualifier组合来强制bean)进行连接参见*2)

编辑:另一个可能的解决方案是使用FactoryBean,尽管我对语法不是100%确定

*一,


*2

这似乎很有用,我会记住这个窍门的。但在我的例子中,类必须决定向哪个主机发送消息。在某些情况下,它会同时使用两个目的地。我明白了,我以为你的问题是关于环境的问题,而不是你实际上使用了两个服务器。如果是这样的话,我不明白你为什么想要一个连接,如果你说你可能需要两个连接。当然,我需要多个连接。我不想像mqConnectionFactoryHost1、mqConnectionFactoryHost2、jmsTemplateHost1、jmsTemplateHost2那样复制此配置。我需要在创建jmsTemplate的过程中指定主机。它看起来非常有用,我会记住这个技巧。但在我的例子中,类必须决定向哪个主机发送消息。在某些情况下,它会同时使用两个目的地。我明白了,我以为你的问题是关于环境的问题,而不是你实际上使用了两个服务器。如果是这样的话,我不明白你为什么想要一个连接,如果你说你可能需要两个连接。当然,我需要多个连接。我不想像mqConnectionFactoryHost1、mqConnectionFactoryHost2、jmsTemplateHost1、jmsTemplateHost2那样复制此配置。我需要在创建jmsTemplate时指定主机。我知道@Resource注释和bean继承,但它不适合我。似乎我需要一个接受主机参数并用相应的连接工厂构造jmsTemplate的工厂。我来试试FactoryBean。非常感谢。正如我在回答中所说的。JMS连接器必须是单体的,否则每次需要初始化每个连接时,都可能会对性能造成巨大的影响。您可能希望将缓存添加到工厂。如果我没有遗漏某些内容,我可以告诉Spring将连接工厂设置为一个单例以共享(在我的情况下)一个物理连接。我知道@Resource annotation和bean继承,但它不适合我。似乎我需要一个接受主机参数并用相应的连接工厂构造jmsTemplate的工厂。我来试试FactoryBean。非常感谢。正如我在回答中所说的。JMS连接器必须是单体的,否则每次需要初始化每个连接时,都可能会对性能造成巨大的影响。您可能希望将缓存添加到工厂中。如果我没有遗漏什么,我可以告诉Spring使连接工厂成为共享(在我的例子中)一个物理连接的单例。
@Value("${db.url}")
private String databaseUrl;
@Value("${db.userName}")
private String userName;
@Value("${db.password}")
private String password;