假设我的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的属性主机设置为此值。”
答案 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/
答案 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;