Key*_*r00 1 java spring dependency-injection spring-boot
可以说我有一个配置类(JmsQueueConfig,见下文).在本课程中,我想为整个应用程序配置多个队列.对于一个队列,没有问题.但是,当我添加第二个队列并尝试从服务(MemberService)使用其中一个队列时,Spring-boot告诉我
com.example.notification.application.jms.JmsEventPublisher中构造函数的参数1需要一个bean,但是找到了2个: - queueAccountToNotification:由类路径资源中的方法'queueAccountToNotification'定义[com/example/notification/application/jms/JmsQueueConfig.class] - queueNotificationToAccount:由类路径资源[com/example/notification/application/jms/JmsQueueConfig.class]中的方法'queueNotificationToAccount'定义
行动:
考虑将其中一个bean标记为@Primary,更新使用者以接受多个bean,或使用@Qualifier标识应该使用的bean
这是我的Config-Class:
@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();
}
}
Run Code Online (Sandbox Code Playgroud)
我的服务:
@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");
}
}
Run Code Online (Sandbox Code Playgroud)
我是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);
}
}
Run Code Online (Sandbox Code Playgroud)
要更正已接受的答案,您对@Qualifier使用的理解是正确的.它可以在两种情况下使用.它可以与@Bean配置方法一起使用,为bean提供限定符.如果未提供,则默认为bean名称.
它也可以用于注射目标,即使用@Autowired或@Inject注释的方法或字段.在此上下文中,如果找到多个bean,它将帮助Spring自动装配基础结构根据限定符(随@Bean方法提供)过滤与注入目标匹配的bean候选者
错误的原因是由于
@AllArgsConstructor
public class JmsEventPublisher implements EventPublisher
Run Code Online (Sandbox Code Playgroud)
@AllArgsConstructor将生成以下构造函数
public JmsEventPublisher(JmsTemplate jmsTemplate, Destination destination){
//body
}
Run Code Online (Sandbox Code Playgroud)
Spring将尝试通过构造函数自动装配JmsEventPublisher,因为它有一个构造函数,它不是无参构造函数.但是,Destination类型的参数匹配两个Queue类型的bean.
解决方案是使用显式构造函数.即删除@AllArgsConstructor并定义constrctor,如下所示
public JmsEventPublisher(JmsTemplate jmsTemplate, @Qualifier("q1")Destination destination){
//body
}
Run Code Online (Sandbox Code Playgroud)
或者使用字段或setter注入,即删除@AllArgsConstructor并注入字段或setter方法
public class JmsEventPublisher implements EventPublisher {
private JmsTemplate jmsTemplate;
@Qualifier("q1")
private Destination destination;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3148 次 |
| 最近记录: |