@Qualifier的@Bean声明不起作用 [英] @Bean declaration with @Qualifier doesn't work

查看:141
本文介绍了@Qualifier的@Bean声明不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以说我有一个配置类(JmsQueueConfig,请参见下文)。在此类中,我想为整个应用程序配置多个队列。对于一个队列,没有问题。但是,当我添加第二个队列并尝试从服务(MemberService)使用这些队列之一时,Spring-boot会告诉我

Lets say I have a config class (JmsQueueConfig, see below). In this class, I want to configure multiple queues for my entire application. For one queue, there is no problem. However when I add a second queue and try to use one of these queues from a service (MemberService), then Spring-boot tells me



com.example.notification.application.jms.JmsEventPublisher
中构造函数的参数1需要单个bean,但是找到了2个:
-queueAccountToNotification:由类路径中的方法'queueAccountToNotification'定义资源
[com / example / notification / application / jms / JmsQueueConfig.class]
-queueNotificationToAccount:由类路径中的方法'queueNotificationToAccount'定义资源
[com / example / notification / application / jms / JmsQueueConfig.class]

Parameter 1 of constructor in com.example.notification.application.jms.JmsEventPublisher required a single bean, but 2 were found: - queueAccountToNotification: defined by method 'queueAccountToNotification' in class path resource [com/example/notification/application/jms/JmsQueueConfig.class] - queueNotificationToAccount: defined by method 'queueNotificationToAccount' in class path resource [com/example/notification/application/jms/JmsQueueConfig.class]

操作:

考虑将其中一个bean标记为@Primary,更新消费者
接受多个bean,或使用@Qualifier标识应消耗的bean

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

此处是我的配置类:

@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上,我还没有找到任何此类文档。

I am new to Spring ecosystem and I might not have understand well the @Autowired and bindings. Any good documentation or example would be much appreciated. On Spring and SoF, I haven't found any such documentation.

已更新:
JmsEventPublisher类

Updated: JmsEventPublisher class

@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);
   }
}


推荐答案

I认为您误解了 @Qualifier

从文档中, 此注释可以在字段或参数上用作候选bean的限定符

在您的情况下, @Qualifier 毫无意义。

In your case @Qualifier is of no meaning.

@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(...)

这并不能解决所有问题。 :)

That doesn't solve all the problem. :)

如异常所示,spring无法自动绑定JmsEventPublisher中的 Destination 字段。因为它有两个类型为Destination(q1和q2)的bean。

要解决这个问题,您可以做的是。

As the exception indicates, spring is not able to autowire Destination field in JmsEventPublisher. Because it has two beans of type Destination(q1 and q2).
To solve this what you can do is .

放入 @Primary 在其中一个bean声明上,然后使用 @Qualifier

Put @Primary on one of the bean declaration and then use @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 能够在多个相同类型的bean的情况下工作,您需要放置 @Primary

Bottom line is For @Qualifier to work in case of multiple beans of same type, you need to put @Primary

另一个选择是使用@Primary而不是@Primary来命名变量,然后spring将自动为您注入正确的bean。即

Another option is instead of using @Primary, you can name the variables exactly as Bean names, then spring will automagically inject correct beans for you. i.e.

public class JmsEventPublisher implements EventPublisher {

  final JmsTemplate jmsTemplate;
  final Destination q1; // q1 or q2
  .....
}

类似MemberService

similiarly in MemberService

public class MemberService {

  @Autowired
  Queue q1; // q1 or q2
  .....

}

这篇关于@Qualifier的@Bean声明不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆