gpt4 book ai didi

java - 策略模式 - 如何注入(inject)策略 - NoUniqueBeanDefinitionException

转载 作者:太空宇宙 更新时间:2023-11-04 11:51:59 26 4
gpt4 key购买 nike

我正在开发一个解决方案来在 SmsService 中实现多个提供程序。我需要一种从我的上下文中注入(inject)策略类的方法。问题是选择取决于外部属性。当我尝试部署此代码时,我得到

<强> org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type

这里我向您展示我的代码:

提供商接口(interface)

public interface SmsProvider {

public Integer send(String user, String password,List<Sms> list);

}

上下文类

@Component
public class ContextProvider {

private @Inject
MessageDAO messageDAO;

private @Inject
SmsProvider strategy;

public Integer send(String user,String password) {

List<Sms> list = extractSmsList();

return strategy.send(user,password, list);
}
public void setStrategy(SmsProvider strategy) {
this.strategy = strategy;
}

策略A

@Component("provider1")
public class Provider1 implements SmsProvider {

private @Inject
MessageDAO messageDAO;

public Integer send(String user, String password, List<Sms> list) {

Status serviceErrorStatus = messageDAO.find(Status.class, 400);
...
}

策略B

@Component("provider2")
public class Provider2 implements SmsProvider{

private @Inject
MessageDAO messageDAO;

@Override
public Integer send(String user, String password, List<Sms> list) {
Status serviceErrorStatus = messageDAO.find(Status.class, 400);
...
}

使用策略。在此类中,我获取属性并在 switch 子句中选择策略。

    @Component
public class SmsServiceImpl implements SmsService{

@Value("${net.mycompany.sms.service.smsProvider}")
private int smsProvider;
private @Inject
MessageDAO messageDAO;
private @Inject
ContextProvider context;
....
public Integer send(String user,String password) {

LOG.debug("Sms provider property setted at: '{}'",smsProvider);
switch (smsProvider) {
case 1:
context.setStrategy(new Provider1());
return context.send(user, password);
case 2:
context.setStrategy(new Provider2());
return context.send(user, password);
}
}

我还尝试删除策略类中的@Component和Context类中smsProvider声明中的@Inject,我在Dao类中得到一个NullPointerException,我真的需要这个daos。我正在使用 Spring 3.2.16-RELEASE 和 Java 7.0.15请帮忙。任何指示都会有帮助提前致谢

编辑我在 tomcat 6 服务器中添加堆栈跟踪:

14:58:48.044 - mycompany_myCompanyFramework_Init[ERROR] - [main] ERROR o.s.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'smsBC': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.service.MessageService net.mycompany.mc.messaging.sms.bc.SmsBCImpl.smsService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'smsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.sms.service.impl.ContextProvider net.mycompany.mc.messaging.sms.service.impl.SmsServiceImpl.context; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contextProvider': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.sms.service.SmsProvider net.mycompany.mc.messaging.sms.service.impl.ContextProvider.strategy; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [net.mycompany.mc.messaging.sms.service.SmsProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1146) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932) ~[spring-context-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479) ~[spring-context-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:389) ~[spring-web-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:294) ~[spring-web-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112) [spring-web-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at net.mycompany.mycompanyframework.component.web.spring.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:37) [mycompanyFramework-web-3.4.5.jar:na]
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4210) [catalina.jar:6.0.39]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4709) [catalina.jar:6.0.39]
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057) [catalina.jar:6.0.39]
at org.apache.catalina.core.StandardHost.start(StandardHost.java:822) [catalina.jar:6.0.39]
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1057) [catalina.jar:6.0.39]
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463) [catalina.jar:6.0.39]
at org.apache.catalina.core.StandardService.start(StandardService.java:525) [catalina.jar:6.0.39]
at org.apache.catalina.core.StandardServer.start(StandardServer.java:754) [catalina.jar:6.0.39]
at org.apache.catalina.startup.Catalina.start(Catalina.java:595) [catalina.jar:6.0.39]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_15]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_15]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_15]
at java.lang.reflect.Method.invoke(Method.java:601) ~[na:1.7.0_15]
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289) [bootstrap.jar:6.0.39]
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414) [bootstrap.jar:6.0.39]
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.service.MessageService net.mycompany.mc.messaging.sms.bc.SmsBCImpl.smsService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'smsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.sms.service.impl.ContextProvider net.mycompany.mc.messaging.sms.service.impl.SmsServiceImpl.context; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contextProvider': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.sms.service.SmsProvider net.mycompany.mc.messaging.sms.service.impl.ContextProvider.strategy; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [net.mycompany.mc.messaging.sms.service.SmsProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
... 29 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'smsService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.sms.service.impl.ContextProvider net.mycompany.mc.messaging.sms.service.impl.SmsServiceImpl.context; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contextProvider': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.sms.service.SmsProvider net.mycompany.mc.messaging.sms.service.impl.ContextProvider.strategy; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [net.mycompany.mc.messaging.sms.service.SmsProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1146) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:912) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:855) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
... 31 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.sms.service.impl.ContextProvider net.mycompany.mc.messaging.sms.service.impl.SmsServiceImpl.context; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contextProvider': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.sms.service.SmsProvider net.mycompany.mc.messaging.sms.service.impl.ContextProvider.strategy; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [net.mycompany.mc.messaging.sms.service.SmsProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
... 42 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contextProvider': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.sms.service.SmsProvider net.mycompany.mc.messaging.sms.service.impl.ContextProvider.strategy; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [net.mycompany.mc.messaging.sms.service.SmsProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1146) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:296) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:293) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:912) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:855) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
... 44 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private net.mycompany.mc.messaging.sms.service.SmsProvider net.mycompany.mc.messaging.sms.service.impl.ContextProvider.strategy; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [net.mycompany.mc.messaging.sms.service.SmsProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:517) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
... 55 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [net.mycompany.mc.messaging.sms.service.SmsProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject()}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:988) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:858) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:489) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
... 57 common frames omitted

最佳答案

我将利用Spring提供的FactoryBean接口(interface)并将SmsProvider的创建封装在适当的位置。当您使用注释配置时,然后根据您的类定义,FactoryBean 配置将如下所示:

首先:我们根据注入(inject)的外部属性封装策略的选择:

@Component
public class SmsProviderFactoryBean implements FactoryBean<SmsProvider>{

@Inject
private ApplicationContext applicationContext;

@Value("${net.mycompany.sms.service.smsProvider}")
private int smsProvider;

@Override
public SmsProvider getObject() throws Exception {
SmsProvider smsProvider = null;

switch (smsProvider) {
case 1:
smsProvider = (SmsProvider) applicationContext.getBean("provider1");
case 2:
smsProvider = (SmsProvider) applicationContext.getBean("provider2");
}

return smsProvider;
}
}

第二:定义配置bean,当'smsProvider' bean将被注入(inject)到其他bean时,将使用getSmsProvder()方法:

@Component
public class Configuration {

@Inject
private ApplicationContext applicationContext;

@Bean(name = "smsProvider")
public SmsProvider getSmsProvider() throws Exception {
return applicationContext.getBean(SmsProviderFactoryBean.class)
.getObject();
}
}

第三:在注入(inject)“smsProvider”时添加@Qualifer(这可能不是必需的,具体取决于您使用的 Spring 版本):

@Component
public class ContextProvider {

@Inject
@Qualifier("smsProvider")
private SmsProvider strategy;

尝试一下。

关于java - 策略模式 - 如何注入(inject)策略 - NoUniqueBeanDefinitionException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41728611/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com