Java Spring FactoryBean 和自动装配不起作用:预期单个匹配 bean 但发现 2

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24455107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 12:18:20  来源:igfitidea点击:

Spring FactoryBean and autowiring not working : expected single matching bean but found 2

javaspringannotationsfactoryautowired

提问by Fab313

I have two classes, each one autowiring the same class through a factory :

我有两个类,每个类都通过工厂自动装配同一个类:

@Service
public class AnalyseDispensationNominativeMetierService implements IAnalyseDispensationNominativeMetierService {

  @Autowired
  @Qualifier("interfaceAutomateServiceFactory")
  private IInterfaceAutomateMetierService interfaceAutomateMetierService;
  [...]


@Service
public class AnalysePreparationGlobaleMetierService implements IAnalysePreparationGlobaleMetierService {

  @Autowired
  @Qualifier("interfaceAutomateServiceFactory")
  private IInterfaceAutomateMetierService interfaceAutomateMetierService;
  [...]


The object I want to create through the factory :

我想通过工厂创建的对象:

@Service
public class InterfaceAutomate implements IInterfaceAutomateMetierService {
[...]


The factory :

工厂 :

@Service("interfaceAutomateServiceFactory")
public class InterfaceAutomateServiceFactory implements FactoryBean<IInterfaceAutomateMetierService> {

  @Autowired(required = true)
  private InterfaceAutomate ijinInterfaceAutomate;

  @Override
  public IInterfaceAutomateMetierService getObject() {
    return ijinInterfaceAutomate;
  }

  @Override
  public Class<?> getObjectType() {
    return IInterfaceAutomateMetierService.class;
  }

  @Override
  public boolean isSingleton() {
    return false;
  }


I keep getting the following error, even though I'm using qualifier annotation... Any idea on what I'm doing wrong ? :

我不断收到以下错误,即使我使用的是限定符注释...知道我做错了什么吗?:

No unique bean of type [IInterfaceAutomateMetierService] is defined: expected single matching bean but found 2: [interfaceAutomate, interfaceAutomateServiceFactory]


Complete stack trace

完整的堆栈跟踪

GRAVE: Exception lors de l'envoi de l'évènement contexte initialisé (context initialized) à l'instance de classe d'écoute (listener) org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'analysePreparationGlobaleMetierService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private dispensation.commun.service.metier.IInterfaceAutomateMetierService dispensation.analysePreparationGlobale.service.metier.impl.AnalysePreparationGlobaleMetierService.interfaceAutomateMetierService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [dispensation.commun.service.metier.IInterfaceAutomateMetierService] is defined: expected single matching bean but found 2: [interfaceAutomate, interfaceAutomateServiceFactory]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:607)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:472)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:388)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:293)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4723)
    at org.apache.catalina.core.StandardContext.call(StandardContext.java:5226)
    at org.apache.catalina.core.StandardContext.call(StandardContext.java:5221)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private dispensation.commun.service.metier.IInterfaceAutomateMetierService dispensation.analysePreparationGlobale.service.metier.impl.AnalysePreparationGlobaleMetierService.interfaceAutomateMetierService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [dispensation.commun.service.metier.IInterfaceAutomateMetierService] is defined: expected single matching bean but found 2: [interfaceAutomate, interfaceAutomateServiceFactory]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:513)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:92)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
    ... 20 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [dispensation.commun.service.metier.IInterfaceAutomateMetierService] is defined: expected single matching bean but found 2: [interfaceAutomate, interfaceAutomateServiceFactory]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:823)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:730)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:485)
    ... 22 more

采纳答案by Fab313

In the end, I solved my problem by changing the name of the factoryBean to match the name of the injected field, and by removing one entry in the scanning of the project. (Could it be that the "double scanning" was causing trouble ?)

最后,我通过更改 factoryBean 的名称以匹配注入字段的名称,并通过删除项目扫描中的一个条目来解决我的问题。(会不会是“双重扫描”惹了麻烦?)

<context:component-scan base-package="dispensation.**.factory.**,dispensation.**.metier.factory.**

=>

=>

<context:component-scan base-package="dispensation.**.factory.**


@Service("interfaceAutomateMetierService")
public class InterfaceAutomateServiceFactory implements FactoryBean<IInterfaceAutomateMetierService> {


@Service
public class AnalysePreparationGlobaleMetierService implements IAnalysePreparationGlobaleMetierService {

  @Autowired
  private IInterfaceAutomateMetierService interfaceAutomateMetierService;

回答by Andrei Stefan

Instead of

代替

@Autowired
@Qualifier("interfaceAutomateServiceFactory")
private IInterfaceAutomateMetierService interfaceAutomateMetierService;

try this

尝试这个

@Resource(name="interfaceAutomateServiceFactory")
private IInterfaceAutomateMetierService interfaceAutomateMetierService;

回答by Jukka

If you can't or don't want to modify the source code, exclude the apparently redundant factory bean by adding an <exclude-filter /> to <context:component-scan />. Also <context:annotation-config /> is implied through <context:component-scan /> by default.

如果您不能或不想修改源代码,请通过将 <exclude-filter /> 添加到 <context:component-scan /> 来排除明显冗余的工厂 bean。另外 <context:annotation-config /> 默认通过 <context:component-scan /> 隐含。

回答by CVS

Using @Primary annotation with your bean(one of them from the two) can solve the issue.The Question however still remains as to why the @Resource annotation for Spring is unable to distinguish based on Autowiring.

对你的 bean 使用 @Primary 注释(两者中的一个)可以解决这个问题。 然而,问题仍然是为什么 Spring 的 @Resource 注释无法基于自动装配进行区分。

Reference "Autowiring two beans implementing same interface - how to set default bean to autowire?"

参考“自动装配两个实现相同接口的 bean - 如何将默认 bean 设置为自动装配?

回答by RAY

The reason why @Resource(name = "{your child class name}") works but @Autowired sometimes don't work is because of the difference of their Matching sequence

@Resource(name = "{your child class name}") 工作但@Autowired 有时不工作的原因是因为它们的匹配顺序不同

Matching sequence of @Autowire:
Type, Qualifier, Name

@Autowire 的匹配顺序:
类型、限定符、名称

Matching sequence of @Resource:
Name, Type, Qualifier

匹配序列@资源
名称,类型,限定符

The more detail explanation can be found here:
Inject and Resource and Autowired annotations

更详细的解释可以在这里找到:
Inject and Resource and Autowired annotations

In this case, different child class inherited from the parent class or interface confuses @Autowire, because they are from same type;

在这种情况下,从父类或接口继承的不同子类会混淆@Autowire,因为它们来自同一类型;

On the other hand, @Resource use Name as first matching priority , it works.

另一方面,@Resource 使用 Name 作为第一匹配优先级,它可以工作。