假设我有一个配置类(Jms队列配置,见下文)。在此类中,我想为整个应用程序配置多个队列。对于一个队列,没有问题。但是,当我添加第二个队列并尝试从服务(成员服务)中使用其中一个队列时,Spring启动会告诉我
com.example.notification.application.jms.JmsEventPublisher 中的构造函数的参数 1 需要一个 Bean,但找到 2 个: - 队列帐户通知:由类路径资源中的方法“队列帐户通知”定义 [com/示例/通知/应用程序/jms/Jms/JmsQueueConfig.class] - 队列通知到帐户:由类路径资源中的方法“队列通知到帐户”定义 [com/示例/通知/应用程序/jms/Jms/JmsQueueConfig.class]
行动:
考虑将其中一个豆子标记为@Primary,更新消费者以接受多个豆子,或使用@Qualifier来识别应该消费的豆子
这是我的配置类:
@Configuration
@EnableJms
@ImportAutoConfiguration(classes = {
JmsAutoConfiguration.class,
ActiveMQAutoConfiguration.class
})
public class JmsQueueConfig {
@Value("${APP_QUEUE_ACCOUNT_TO_NOTIFICATION}")
private String queueAccountToNotificationName;
@Value("${APP_QUEUE_NOTIFICATION_TO_ACCOUNT}")
private String queueNotificationNameToAccount;
@Bean
@Qualifier("q1")
public Queue queueAccountToNotification() {
return new ActiveMQQueue(queueAccountToNotificationName);
}
@Bean
@Qualifier("q2")
public Queue queueNotificationToAccount() {
return new ActiveMQQueue(queueNotificationNameToAccount);
}
@Bean
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
@Bean
@Qualifier("p1")
public EventPublisher eventPublisher(JmsTemplate jmsTemplate) {
return new JmsEventPublisher(jmsTemplate, new ActiveMQQueue(queueAccountToNotificationName));
}
@Bean
public MessageConverter messageConverter() {
return new JmsMessageConverter();
}
}
我的服务:
@Service
@FieldDefaults(level = AccessLevel.PRIVATE)
@AllArgsConstructor
@Slf4j
public class MemberService {
@Autowired
@Qualifier("q1")
Queue q;
@Qualifier("p1")
EventPublisher eventPublisher;
public void createMemberSubscription(final Member member) {
final MembershipSubscriptionEvent event = new MembershipSubscriptionEvent(UUID.randomUUID().toString(), member.getEmail());
//eventPublisher.publish(event);
log.info("createMemberSubscription");
}
public void removeMemberSubscription(final Member member) {
final MembershipRemovalEvent event = new MembershipRemovalEvent(UUID.randomUUID().toString());
//eventPublisher.publish(event);
log.info("removeMemberSubscription");
}
}
我是Spring生态系统的新手,可能还没有很好地理解@Autowired和绑定。任何好的文件或例子将不胜感激。在Spring和SoF上,我没有找到任何这样的文档。
更新时间:Jms事件发布者类
@Component
@FieldDefaults(level = AccessLevel.PRIVATE)
@Slf4j
@AllArgsConstructor
public class JmsEventPublisher implements EventPublisher {
final JmsTemplate jmsTemplate;
final Destination destination;
@Override
public void publish(DomainEvent event) {
jmsTemplate.convertAndSend(destination, event);
log.trace("Sent event. [destination={}, event={}]", destination, event);
}
}
将< code >最终目的地destination更改为< code >最终目的地q1,应该可以工作。我也有同样的问题,但它对我有效。
我认为您误解了@Qualifier
从文档中,“在自动连接时,此注释可能用于字段或参数,作为候选bean的限定符。”
在您的情况下,@Qualifier
没有任何意义。
@Bean
@Qualifier("q1")
public Queue queueAccountToNotification() {
return new ActiveMQQueue(queueAccountToNotificationName);
}
相反,你应该这样做
@Bean(name = "q1")
public Queue queueAccountToNotification() {
return new ActiveMQQueue(queueAccountToNotificationName);
}
@Bean(name = "q2")
public Queue queueNotificationToAccount() {
return new ActiveMQQueue(queueNotificationNameToAccount);
}
同样,删除事件发布者(...)
上的@Qualifier
这并不能解决所有问题。:)
正如异常指出的,spring不能自动连接JmsEventPublisher中的< code>Destination字段。因为它有两个类型为Destination的beans和q2)。< br >要解决这个问题,您可以做的是。
将@Primary
放在其中一个bean声明上,然后使用@Qualifier
。
@Primary
@Bean(name = "q1")
public Queue queueAccountToNotification() {
return new ActiveMQQueue(queueAccountToNotificationName);
}
public class JmsEventPublisher implements EventPublisher {
final JmsTemplate jmsTemplate;
@Qualifier("q1")
final Destination destination;
..........
}
底线是,为了让@Qualifier
在多个相同类型的豆子的情况下工作,你需要把@Primary
另一种选择是不使用@Main,您可以将变量命名为Bean名称,然后Spring会自动为您注入正确的bean。即。
public class JmsEventPublisher implements EventPublisher {
final JmsTemplate jmsTemplate;
final Destination q1; // q1 or q2
.....
}
类似地在会员服务中
public class MemberService {
@Autowired
Queue q1; // q1 or q2
.....
}
要纠正已接受的答案,你对@限定词用法的理解是正确的。它可以在两种情况下使用。它可以与@Bean配置方法一起使用,为Bean提供限定符。如果未提供,则默认为bean名称。
它还可以用于注入目标,即带有@Autowired或@Inject注释的方法或字段。在这种情况下,如果找到多个bean,它可以帮助Spring自动连接基础设施根据限定符(@bean方法提供)筛选匹配注入目标的bean候选
错误的原因是
@AllArgsConstructor
public class JmsEventPublisher implements EventPublisher
@AllArgsConstructor将生成以下构造函数
public JmsEventPublisher(JmsTemplate jmsTemplate, Destination destination){
//body
}
Spring将尝试通过构造函数自动连接JmsEventPublisher,因为它有一个不是无参数构造函数的构造函数。但是,类型Destination的参数匹配两个类型Queue的beans。
解决方案是使用显式构造器。即删除@AllArgsConstructor并定义constrctor,如下所示
public JmsEventPublisher(JmsTemplate jmsTemplate, @Qualifier("q1")Destination destination){
//body
}
或使用field或setter注入代替,即删除@AllArgsConstructor并注入字段或setter方法
public class JmsEventPublisher implements EventPublisher {
private JmsTemplate jmsTemplate;
@Qualifier("q1")
private Destination destination;
}
我正试图编写代码,从一个Android应用程序发送一条短信,但当我试图发送短信时,它给我返回了错误: 我检查了,但我拥有清单中的权限,如下所示: null null 我在网上搜索了一下,但是所有的错误都是关于语法的,你能帮我一下吗?
请说出这段代码有什么问题。
问题内容: 我想知道是否有人可以在CSS中!important声明 无法 覆盖内联样式时放些权威参考摘要。 问题答案: 确定哪些样式相互替代涉及许多因素。样式声明出现在 级联中 的位置越低,则它在定位元素时 越具体 ,则与其他样式的权衡就越大。 这是样式继承的CSS2标准: 如果级联产生一个值,请使用它。 否则,如果属性是继承的,则使用父元素的值,通常是计算值。 否则,请使用属性的初始值。每个属性
我生成doc与发音插件和它的工作,我添加了一个源目录添加额外的文件到类路径编译(maven-编译器插件).发音不工作与this.how我解决这个问题?我得到这个错误:[ERROR]未能执行目标org.codehaus.enunciate: maven-en
我发现以下错误: 错误:变量或字段“foo”声明为void 错误:“a”之前应为“)” 错误:在'b'之前预期')' 在函数“int main()”中:错误:“foo”未在此范围内声明