Java 未定义唯一类型的 bean:预期单个匹配 bean,但发现 2

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22300102/
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-13 14:49:12  来源:igfitidea点击:

No unique bean of type is defined: expected single matching bean but found 2

javaspringjavabeans

提问by user2334926

I am getting the below exception when I am deploying the code

部署代码时出现以下异常

 Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.belk.api.adapter.contract.Adapter] is defined: expected single matching bean but found 2: [endeca, solar]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:800)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
    ... 64 more

I have 3 different projects one is Common, second is Adapter and the third is Service. The adapter is dependent on Common and Service is dependent on Adapter. All three are maven projects. Now in my Common project I have an interface called CommonAdapter.java

我有 3 个不同的项目,一个是 Common,第二个是 Adapter,第三个是 Service。适配器依赖于 Common,而 Service 依赖于 Adapter。这三个都是maven项目。现在在我的 Common 项目中,我有一个名为 CommonAdapter.java 的接口

 public interface CommonAdapter {
    List service() ;
}

I have a class called AdapterFactory.java in the same project (i,e Common)

我在同一个项目中有一个名为 AdapterFactory.java 的类(即通用)

@Component
public class AdapterFactory {
    @Autowired
    Adapter adapter;
    public Adapter getAdapter(String adapterName){
        return adapter;
    }

}   
    <context:component-scan base-package="com.test.api" />
    <bean
        class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean"
        id="adapterFactory">
        <property name="serviceLocatorInterface" value="com.test.api.adapter.manager.AdapterFactory">
        </property>
    </bean>

Now in my Adapter Project, I have the implementation classes for CommonAdapter.java One is EndecaAdapetr.java and the other is SolarAdapter.java

现在在我的适配器项目中,我有 CommonAdapter.java 的实现类,一个是 EndecaAdapetr.java,另一个是 SolarAdapter.java

@Component("endeca")
public class EndecaAdapter implements Adapter {
    List service() {
    // My bussiness logic
    }
}

@Component("solar")
public class SolarAdapter implements Adapter {
    List service() {
    // My bussiness logic
    }
}

Now in my Service project, want to invoke the service method of the above two classes based on the input.

现在在我的Service项目中,想根据输入调用上面两个类的service方法。

public class ProductSearchServiceImpl {
    @Autowired
    private AdapterFactory adapterFactory;
    public Search searchProducts(){
    Adapter endecaAdapter = this.adapterFactory
                .getAdapter("endeca ");
 }
 }

回答by Andrei Nicusan

@Autowiredworks only when there is no doubt on which container-managed instance should be injected. Basically, this can be attained in (at least) 3 ways:

@Autowired仅当毫无疑问应该注入哪个容器管理的实例时才有效。基本上,这可以通过(至少)三种方式实现:

  1. There is only one container-managed bean that IS-A declared type of the autowired field;
  2. There are more container-managed beans that validate the above IS-A condition, but the autowired field is also qualified (in Spring, by using a @Qualifierannotation)
  3. You don't use @Autowired, but rather inject the beans by name.
  1. 只有一个容器管理的 bean 是自动装配字段的 IS-A 声明类型;
  2. 有更多容器管理的 bean 可以验证上述 IS-A 条件,但自动装配的字段也是限定的(在 Spring 中,通过使用@Qualifier注释)
  3. 您不使用@Autowired,而是按名称注入 bean。

In your case, you have two beans that validate the IS-A condition:

在您的情况下,您有两个可验证 IS-A 条件的 bean:

endecaIS-A Adapter

endecaIS-A Adapter

and

solarIS-A Adapter.

solar是-A Adapter

So the container does not have a unique autowire candidate, therefore it crashes while setting up itself.

所以容器没有唯一的自动装配候选者,因此它在设置自身时崩溃。

回答by Abhishek Nayak

Use @Primaryand @Resourcewhen you have multiple implementation classes.

当您有多个实现类时使用@Primaryand @Resource

@Primary 
@Component("endeca")
public class EndecaAdapter implements Adapter {
    List service() {
    // My bussiness logic
    }
}

@Component("solar")
public class SolarAdapter implements Adapter {
    List service() {
    // My bussiness logic
    }
}

and inject like:

并注入:

@Resource("solar")
Adapter solarAdapter;

回答by Seba Echarte

There are another JPA standard solution: You can use @named and @inject, so the example will be like this:

还有另一种 JPA 标准解决方案:您可以使用 @named 和 @inject,因此示例将如下所示:

public iterface Adapter {

}

@Named
public class EndecaAdapter implements Adapter {
    List service() {
    // My bussiness logic
    }
}



@Named
public class SolarAdapter implements Adapter {
    List service() {
    // My bussiness logic
    }
}

and Inject will be like this:

和注入将是这样的:

@Inject @Named("SolarAdapter")
Adapter solarAdapter;

You don't need, put name, Spring do it by herself :)

你不需要,输入名字,Spring 自己做 :)

回答by user2065095

Already resolved here.

这里已经解决

You must inject component with @javax.annotation.Resource(name="componentName").

您必须使用@javax.annotation.Resource(name="componentName").