org.springframework.beans.factory.NoUniqueBeanDefinitionException

看书和实践中,自己体会了一下这个异常org.springframework.beans.factory.NoUniqueBeanDefinitionException

该异常如何产生
该异常如何解决

先来看一下下面的代码:

Animal.java接口:

package com.example.demo.chapter3;

public interface Animal {
    void use();
}

Person.java接口

package com.example.demo.chapter3;

public interface Person {
    void service();
    void setAnimal(Animal animal);
}

3个实现类:

BussinessPerson.java

package com.example.demo.chapter3;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BussinessPerson implements Person {
    /**
     * 该注解的注入机制最基本的额一条是根据类型
     * 首先根据类型找到对应的Bean,如果对应类型的Bean不是唯一的,那么它根据其属性名称和Bean的名称进行匹配
     * 如果匹配的上,就会使用该Bean;如果无法匹配,就会抛出异常。
     * 是一个默认必须找到对应Bean的注解,如果不能确定其标注属性一定会存在并且允许这个被标注的属性为null,此时可以
     * 进行如下的配置@AutoWired属性required为false
     * 还可以标注方法 对方法的参数进行注入
     */
    @Autowired
    private Animal animal;
    @Override
    public void service() {
        this.animal.use();
    }

    @Override
    public void setAnimal(Animal animal) {
        this.animal = animal;
    }
}

Dog.java:

package com.example.demo.chapter3;

import org.springframework.stereotype.Component;

@Component
public class Dog implements Animal {
    @Override
    public void use() {
        System.out.println("狗【"+Dog.class.getSimpleName()+"】是看门的");
    }
}

Cat.java:

package com.example.demo.chapter3;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

/**
 * @Primary注解 当发现有多个同样类型的Bean的时候,优先使用该注解所注解的类型。
 */
@Component
public class Cat implements Animal {
    @Override
    public void use() {
        System.out.println("狗【"+ Cat.class.getSimpleName()+"】是看门的");
    }
}

Application.java:

package com.example.demo;

import com.example.demo.chapter3.BussinessPerson;
import com.example.demo.chapter3.Person;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        /*SpringApplication springApplication = new SpringApplication(Application.class);
        springApplication.run(args);*/

        ApplicationContext ctx = new AnnotationConfigApplicationContext(Application.class);
        Person person = ctx.getBean(BussinessPerson.class);
        person.service();
    }
}

异常:

D:\Java8\jdk1.8.0_211\bin\java.exe -Dvisualvm.id=304768462127000 -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.1\lib\idea_rt.jar=65141:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1.1\bin" -Dfile.encoding=UTF-8 -classpath D:\Java8\jdk1.8.0_211\jre\lib\charsets.jar;D:\Java8\jdk1.8.0_211\jre\lib\deploy.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\access-bridge-64.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\cldrdata.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\dnsns.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\jaccess.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\jfxrt.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\localedata.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\nashorn.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\sunec.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\sunjce_provider.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\sunmscapi.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\sunpkcs11.jar;D:\Java8\jdk1.8.0_211\jre\lib\ext\zipfs.jar;D:\Java8\jdk1.8.0_211\jre\lib\javaws.jar;D:\Java8\jdk1.8.0_211\jre\lib\jce.jar;D:\Java8\jdk1.8.0_211\jre\lib\jfr.jar;D:\Java8\jdk1.8.0_211\jre\lib\jfxswt.jar;D:\Java8\jdk1.8.0_211\jre\lib\jsse.jar;D:\Java8\jdk1.8.0_211\jre\lib\management-agent.jar;D:\Java8\jdk1.8.0_211\jre\lib\plugin.jar;D:\Java8\jdk1.8.0_211\jre\lib\resources.jar;D:\Java8\jdk1.8.0_211\jre\lib\rt.jar;D:\demo\target\classes;C:\maven\mvn_repo3.0\org\springframework\boot\spring-boot-starter-web\2.1.5.RELEASE\spring-boot-starter-web-2.1.5.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\boot\spring-boot-starter\2.1.5.RELEASE\spring-boot-starter-2.1.5.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\boot\spring-boot-starter-logging\2.1.5.RELEASE\spring-boot-starter-logging-2.1.5.RELEASE.jar;C:\maven\mvn_repo3.0\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\maven\mvn_repo3.0\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\maven\mvn_repo3.0\org\apache\logging\log4j\log4j-to-slf4j\2.11.2\log4j-to-slf4j-2.11.2.jar;C:\maven\mvn_repo3.0\org\apache\logging\log4j\log4j-api\2.11.2\log4j-api-2.11.2.jar;C:\maven\mvn_repo3.0\org\slf4j\jul-to-slf4j\1.7.26\jul-to-slf4j-1.7.26.jar;C:\maven\mvn_repo3.0\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;C:\maven\mvn_repo3.0\org\yaml\snakeyaml\1.23\snakeyaml-1.23.jar;C:\maven\mvn_repo3.0\org\springframework\boot\spring-boot-starter-json\2.1.5.RELEASE\spring-boot-starter-json-2.1.5.RELEASE.jar;C:\maven\mvn_repo3.0\com\fasterxml\jackson\core\jackson-databind\2.9.8\jackson-databind-2.9.8.jar;C:\maven\mvn_repo3.0\com\fasterxml\jackson\core\jackson-annotations\2.9.0\jackson-annotations-2.9.0.jar;C:\maven\mvn_repo3.0\com\fasterxml\jackson\core\jackson-core\2.9.8\jackson-core-2.9.8.jar;C:\maven\mvn_repo3.0\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.9.8\jackson-datatype-jdk8-2.9.8.jar;C:\maven\mvn_repo3.0\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.9.8\jackson-datatype-jsr310-2.9.8.jar;C:\maven\mvn_repo3.0\com\fasterxml\jackson\module\jackson-module-parameter-names\2.9.8\jackson-module-parameter-names-2.9.8.jar;C:\maven\mvn_repo3.0\org\springframework\boot\spring-boot-starter-tomcat\2.1.5.RELEASE\spring-boot-starter-tomcat-2.1.5.RELEASE.jar;C:\maven\mvn_repo3.0\org\apache\tomcat\embed\tomcat-embed-core\9.0.19\tomcat-embed-core-9.0.19.jar;C:\maven\mvn_repo3.0\org\apache\tomcat\embed\tomcat-embed-el\9.0.19\tomcat-embed-el-9.0.19.jar;C:\maven\mvn_repo3.0\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.19\tomcat-embed-websocket-9.0.19.jar;C:\maven\mvn_repo3.0\org\hibernate\validator\hibernate-validator\6.0.16.Final\hibernate-validator-6.0.16.Final.jar;C:\maven\mvn_repo3.0\javax\validation\validation-api\2.0.1.Final\validation-api-2.0.1.Final.jar;C:\maven\mvn_repo3.0\org\jboss\logging\jboss-logging\3.3.2.Final\jboss-logging-3.3.2.Final.jar;C:\maven\mvn_repo3.0\com\fasterxml\classmate\1.4.0\classmate-1.4.0.jar;C:\maven\mvn_repo3.0\org\springframework\spring-web\5.1.7.RELEASE\spring-web-5.1.7.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\spring-beans\5.1.7.RELEASE\spring-beans-5.1.7.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\spring-webmvc\5.1.7.RELEASE\spring-webmvc-5.1.7.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\spring-aop\5.1.7.RELEASE\spring-aop-5.1.7.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\spring-context\5.1.7.RELEASE\spring-context-5.1.7.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\spring-expression\5.1.7.RELEASE\spring-expression-5.1.7.RELEASE.jar;C:\maven\mvn_repo3.0\org\slf4j\slf4j-api\1.7.26\slf4j-api-1.7.26.jar;C:\maven\mvn_repo3.0\org\springframework\spring-core\5.1.7.RELEASE\spring-core-5.1.7.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\spring-jcl\5.1.7.RELEASE\spring-jcl-5.1.7.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\boot\spring-boot-devtools\2.1.5.RELEASE\spring-boot-devtools-2.1.5.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\boot\spring-boot\2.1.5.RELEASE\spring-boot-2.1.5.RELEASE.jar;C:\maven\mvn_repo3.0\org\springframework\boot\spring-boot-autoconfigure\2.1.5.RELEASE\spring-boot-autoconfigure-2.1.5.RELEASE.jar;C:\maven\mvn_repo3.0\com\alibaba\fastjson\1.2.47\fastjson-1.2.47.jar;C:\maven\mvn_repo3.0\com\google\code\gson\gson\2.8.5\gson-2.8.5.jar;C:\maven\mvn_repo3.0\org\projectlombok\lombok\1.18.6\lombok-1.18.6.jar;C:\maven\mvn_repo3.0\org\apache\commons\commons-dbcp2\2.1.1\commons-dbcp2-2.1.1.jar;C:\maven\mvn_repo3.0\org\apache\commons\commons-pool2\2.6.2\commons-pool2-2.6.2.jar;C:\maven\mvn_repo3.0\mysql\mysql-connector-java\8.0.15\mysql-connector-java-8.0.15.jar;C:\maven\mvn_repo3.0\com\alibaba\druid\1.1.16\druid-1.1.16.jar com.example.demo.Application
21:18:09.503 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@326de728
21:18:09.538 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
21:18:09.649 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\demo\target\classes\com\example\demo\chapter3\BussinessPerson.class]
21:18:09.650 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\demo\target\classes\com\example\demo\chapter3\Cat.class]
21:18:09.651 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\demo\target\classes\com\example\demo\chapter3\Dog.class]
21:18:10.051 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.jmx.enabled' in PropertySource 'systemProperties' with value of type String
21:18:10.054 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.application.admin.enabled' in PropertySource 'systemProperties' with value of type String
21:18:10.194 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.condition.BeanTypeRegistry'
21:18:10.276 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.jmx.enabled' in PropertySource 'systemProperties' with value of type String
21:18:10.288 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.application.admin.enabled' in PropertySource 'systemProperties' with value of type String
21:18:10.558 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'propertySourcesPlaceholderConfigurer'
21:18:10.570 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
21:18:10.571 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata'
21:18:10.572 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
21:18:10.578 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
21:18:10.579 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
21:18:10.583 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor'
21:18:10.585 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'methodValidationPostProcessor'
21:18:10.609 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Autowiring by type from bean name 'methodValidationPostProcessor' via factory method to bean named 'environment'
21:18:10.627 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'application'
21:18:10.632 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bussinessPerson'
21:18:10.641 [main] WARN org.springframework.context.annotation.AnnotationConfigApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bussinessPerson': Unsatisfied dependency expressed through field 'animal'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.demo.chapter3.Animal' available: expected single matching bean but found 2: cat,dog
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bussinessPerson': Unsatisfied dependency expressed through field 'animal'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.demo.chapter3.Animal' available: expected single matching bean but found 2: cat,dog
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:843)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
	at org.springframework.context.annotation.AnnotationConfigApplicationContext.(AnnotationConfigApplicationContext.java:88)
	at com.example.demo.Application.main(Application.java:15)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.demo.chapter3.Animal' available: expected single matching bean but found 2: cat,dog
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:221)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1226)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1168)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
	... 14 more

Process finished with exit code 1

可以从上面的异常信息看出主要是因为getBean方法返回实例对象,但是因为BussinessPerson.java中使用@AutoWired注解注入了Animal接口,又因为Cat.javaDog.java都实现了Animal接口,所以此时Spring并不知道该注入谁,所以才产生了上面的异常。
在这里插入图片描述

如何解决这个问题:

  • 书中 有提到,可以使用@Qualifier(value = "dog")来解决或者采用private Animal dog;的方式,因为Spring@AutoWired是根据类型来查找对应的Bean,还可以通过类型+name的形式去查找对应的bean
  • 可以使用注解@Primary,该注解表示当发现有多个同样类型的Bean的时候,优先使用该注解所注解的类型。

最后的运行结果如下:

狗【Cat】是看门的

阅读《深入浅出Spring Boot2.x》总结

org.springframework.beans.factory.NoUniqueBeanDefinitionException_第1张图片

你可能感兴趣的:(spring)