我正在spring-boot-starter-activemq
使用PoolFactory
。一切都很好,并且很容易通过application.yaml
配置,但我找不到正确的方法来注入我的自定义RedeliveryPolicy
。所以问题是我该怎么做?
答案 0 :(得分:5)
可以在连接工厂上设置重新传递策略。由于弹簧引导自动配置连接工厂,您可以添加一个方法来设置它。
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Foo
{
@Bean
public InitializingBean connectionFactory(ActiveMQConnectionFactory connectionFactory)
{
return () ->
{
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
// configure redelivery policy
connectionFactory.setRedeliveryPolicy(redeliveryPolicy);
};
}
}
<强>更新强>
如一个回复中所述,如果未设置以下配置spring.activemq.pool.enabled = true
,则上述解决方案效果很好。
使用池连接工厂时,Spring Boot会自动配置org.apache.activemq.pool.PooledConnectionFactory
而不是org.apache.activemq.ActiveMQConnectionFactory
。此配置在此处发生:org.springframework.boot.autoconfigure.jms.activemq.ActiveMQConnectionFactoryConfiguration.PooledConnectionFactoryConfiguration#pooledJmsConnectionFactory
在以下行中:
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(new ActiveMQConnectionFactoryFactory(properties,factoryCustomizers.getIfAvailable()).createConnectionFactory(ActiveMQConnectionFactory.class));
为了完成这项工作,您有两种选择:
在注入bean ActiveMQConnectionFactory
时使用PooledConnectionFactory
和javax.jms.ConnectionFactory
的公共父级,并使用instance-of和cast来设置重新传递策略。
@Bean
public InitializingBean connectionFactory(ConnectionFactory connectionFactory) {
if (connectionFactory instanceof ActiveMQConnectionFactory) {
return configureRedeliveryPolicy((ActiveMQConnectionFactory) connectionFactory);
} else if (connectionFactory instanceof PooledConnectionFactory) {
final PooledConnectionFactory pooledConnectionFactory = (PooledConnectionFactory) connectionFactory;
if (pooledConnectionFactory.getConnectionFactory() instanceof ActiveMQConnectionFactory) {
return configureRedeliveryPolicy((ActiveMQConnectionFactory) pooledConnectionFactory.getConnectionFactory());
}
}
// ...
}
为每种bean类型提供两种不同的自定义初始化方案,基本上与1相同,但您正在利用ConditionalOnBean
而不是检查connectionFactory类类型。
@Configuration
public class Foo {
@Bean
@ConditionalOnBean(ActiveMQConnectionFactory.class)
public InitializingBean connectionFactory(ActiveMQConnectionFactory connectionFactory) {
return configureRedeliveryPolicy(connectionFactory);
}
@Bean
@ConditionalOnBean(PooledConnectionFactory.class)
public InitializingBean pooledConnectionFactory(PooledConnectionFactory connectionFactory) {
if (connectionFactory.getConnectionFactory() instanceof ActiveMQConnectionFactory) {
return configureRedeliveryPolicy((ActiveMQConnectionFactory) connectionFactory.getConnectionFactory());
} else return () -> {
// do something else
};
}
private InitializingBean configureRedeliveryPolicy(ActiveMQConnectionFactory connectionFactory) {
return () ->
{
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
// configure redelivery policy
connectionFactory.setRedeliveryPolicy(redeliveryPolicy);
};
}
}
答案 1 :(得分:1)
我尝试了@Iulian Rosca的答案,但不适用于最新版本的spring-boot-starter-activemq(我使用的是2.2.0.RELEASE版本)。
Spring为ConnectionFactory
提供了许多其他实现类,例如CachingConnectionFactory
,JmsPooledConnectionFactory
,...,并且它们彼此之间没有继承。因此,上述解决方案需要使用多种类类型进行重构。
我发现Spring提供了一个功能接口ActiveMQConnectionFactoryCustomizer
,无论创建哪个类,该接口都会在创建ActiveMQ Connection Factory时注入。它将自定义连接工厂类,您可以设置任何属性,而不仅仅是重新交付策略。
这是我的示例代码:
@Configuration
public class RedeliveryCofiguration {
@Bean
public ActiveMQConnectionFactoryCustomizer configureRedeliveryPolicy() {
return connectionFactory ->
{
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
// configure redelivery policy
connectionFactory.setRedeliveryPolicy(redeliveryPolicy);
};
}
}