可以说我有一个配置类(JmsQueueConfig,请参见下文)。在此类中,我想为整个应用程序配置多个队列。对于一个队列,没有问题。但是,当我添加第二个队列并尝试从服务(MemberService)使用这些队列之一时,Spring- boot会告诉我
com.example.notification.application.jms.JmsEventPublisher中的构造函数的参数1需要一个bean,但是找到2:-queueAccountToNotification:由类路径资源[com / example / notification / application / jms /中的方法’queueAccountToNotification’定义[JmsQueueConfig.class]-queueNotificationToAccount:由类路径资源[com / example / notification / application / jms / JmsQueueConfig.class]中的方法’queueNotificationToAccount’定义 行动: 考虑将其中一个Bean标记为@Primary,更新使用者以接受多个Bean,或使用@Qualifier标识应使用的Bean
com.example.notification.application.jms.JmsEventPublisher中的构造函数的参数1需要一个bean,但是找到2:-queueAccountToNotification:由类路径资源[com / example / notification / application / jms /中的方法’queueAccountToNotification’定义[JmsQueueConfig.class]-queueNotificationToAccount:由类路径资源[com / example / notification / application / jms / JmsQueueConfig.class]中的方法’queueNotificationToAccount’定义
行动:
考虑将其中一个Bean标记为@Primary,更新使用者以接受多个Bean,或使用@Qualifier标识应使用的Bean
这是我的配置类:
@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上,我还没有找到任何此类文档。
更新: JmsEventPublisher类
@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); } }
我认为您@Qualifier 对文档有误解,“ 在自动装配时 , 此注释可以在字段或参数上用作候选bean的限定符。 ”
@Qualifier
在你的情况下@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上eventPublisher(...)
eventPublisher(...)
那并不能解决所有问题。:)
如异常所示,spring无法自动Destination绑定JmsEventPublisher中的字段。因为它有两个类型为Destination(q1和q2)的bean。 为了解决这个问题,您可以做的是。
Destination
放入@Primary其中一个bean声明,然后使用@Qualifier。
@Primary
@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在多个相同类型的bean的情况下工作,您需要@Primary
另一个选择是使用@Primary而不是@Primary,可以将变量命名为与Bean名称完全相同的名称,然后spring将自动为您注入正确的Bean。即
public class JmsEventPublisher implements EventPublisher { final JmsTemplate jmsTemplate; final Destination q1; // q1 or q2 ..... }
类似地在MemberService中
public class MemberService { @Autowired Queue q1; // q1 or q2 ..... }