看书和实践中,自己体会了一下这个异常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.java
和Dog.java
都实现了Animal
接口,所以此时Spring
并不知道该注入谁,所以才产生了上面的异常。
@Qualifier(value = "dog")
来解决或者采用private Animal dog;
的方式,因为Spring
的@AutoWired
是根据类型来查找对应的Bean,还可以通过类型+name
的形式去查找对应的bean
。@Primary
,该注解表示当发现有多个同样类型的Bean的时候,优先使用该注解所注解的类型。狗【Cat】是看门的
阅读《深入浅出Spring Boot2.x》总结