我正在尝试使用Spring实现基于策略模式的通信服务功能。我有以下课程 -
界面 - MessageService.java
package com.xxx
public Interface MessageService{
String sendMessage(String idOrNumber);
}
实施类 -
1)EmailService.java
package com.xxx
@Component
public class EmailService implements MessageService{
public String sendMessage(String idOrNumber){
// Do some operation
return "success"
}
}
2)SmsService.java
package com.xxx
@Component
public class SmsService implements MessageService{
public String sendMessage(String idOrNumber){
// Do some operation
return "success"
}
}
CommunicationFactory Class
package com.xxx
@Component
public class CommunicationFactory {
@Resource(name ="smsService")
private SmsService smsService
@Resource(name ="emailService")
private EmailService emailService;
public MessageService getCommunicationChannel(String channel){
MessageService messageService = null;
if("sms".equals(channel){
messageService = smsService;
}
if("email".equals(channel){
messageService = emailService;
}
return messageService;
}
我有一个邮件服务实现类
package com.xxx
@Component
@Service
public class CommunicationServiceImpl implements CommunicationService {
@Autowired
private MessageService messageService;
CommunicationFactory communicationFactory;
@Override
public String sendCommunication(String idOrNumber){
//Which implementation be called - SMS or EMAIL
messageService = communicationFactory.getCommunicationChannel(channel);
String statusMessage = messageService.sendMessage(idOrNumber);
}
}
运行服务器时出现以下错误。
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.xxx.MessageService com.xxx.CommunicationServiceImpl.messageService; nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.xxx.MessageService] is defined: expected single matching bean but found 2: smsService,emailService
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:514) [spring-beans-
3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) [spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285) [spring-beans-
3.2.3.RELEASE.jar:3.2.3.RELEASE]
... 25 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.xxx.MessageService] is defined: expected single matching bean but found 2:
smsService,emailService
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:863) [spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:768) [spring-beans-3.2.3.RELEASE.jar:3.2.3.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486) [spring-beans-
3.2.3.RELEASE.jar:3.2.3.RELEASE]
... 27 more
我哪里错了?任何指针都会有所帮助
答案 0 :(得分:1)
试试这个。
实施类 -
1) EmailService.java
package com.xxx
@Component("emailService")
public class EmailService implements MessageService{
public String sendMessage(String idOrNumber){
// Do some operation
return "success"
}
}
2) SmsService.java
package com.xxx
@Component("smsService")
public class SmsService implements MessageService{
public String sendMessage(String idOrNumber){
// Do some operation
return "success"
}
}
问题在于:
@Autowired
private MessageService messageService;
可能的解决方案是@Autowired两种服务。
@Autowired
private MessageService smsService;
@Autowired
private MessageService emailService;
或者,如果您遇到同样的问题。
@Autowired
@Qualifier("smsService")
private MessageService smsService;
@Autowired
@Qualifier("emailService")
private MessageService emailService;
答案 1 :(得分:0)
我知道最简单的实现是依赖注入的服务列表并使用get方法来获取负责任的服务:
package com.xxx
@Component
public class CommunicationFactory {
/**
* This list would be ordered if the interface is implementing `org.springframework.core.Ordered` or an implementation declares `@org.springframework.core.annotation.Order`(in Spring 4)
*/
@Autowired
private List<MessageService> messageServices;
/**
* @return the FIRST communication channel for the given channel
*/
public MessageService getCommunicationChannel(String channel){
for (MessageService ms : messageServices) {
if (ms.supports(channel)) {
return ms;
}
}
return null; // or a default :)
}
/**
* With this implementation you can even have multiple implementations firing a message if they support the given channel.
* @return a list of communication channels that support the given channel
*/
public List<MessageService> getCommunicationChannels(String channel){
List<MessageService> supporting = new ArrayList<>();
for (MessageService ms : messageServices) {
if (ms.supports(channel)) {
supporting.add(ms);
}
}
return supporting;
}
}