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

时间:2013-09-23 12:59:04

标签: java spring inversion-of-control

假设我的Spring xml中有以下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。

将主机指定为以下内容会很棒:

class A {
    @Autowired(host="host1")
    private JmsTemplate jmsTemplate;
}

class B {
    @Autowired(host="host2")
    private JmsTemplate jmsTemplate;
}

更新

我可以创建以下配置:

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

然后:

class A {
    @Resource("jmsTemplate1")
    private JmsTemplate jmsTemplate;
}

class B {
    @Resource("jmsTemplate2")
    private JmsTemplate jmsTemplate;
}

这似乎是错误和复杂的。问题是减少此配置并将主机作为参数传递。换句话说,我想告诉Spring:“创建jmsTemplate并将connectionFactory的属性主机设置为此值。”

2 个答案:

答案 0 :(得分:1)

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

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

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

* 1 http://www.mkyong.com/spring/spring-bean-configuration-inheritance/

* 2 Autowiring spring bean by name using annotation

答案 1 :(得分:0)

这就是我的所作所为:

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

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

在这里你可以看到我使用了一个名为{db.environment}的环境变量,如果未定义该值,则默认为dev形成文件名db.dev.properties

我的下一步是在运行应用程序的不同环境中定义变量

java -Ddb.environenment=prod ...

由于我使用Tomcat,我在sentenv.sh中定义了该变量,但我很确定其他应用服务器提供了类似的机制。

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

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