问题描述
Exception in thread “main” org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.wcf.demo08.IAService’ available: expected single matching bean but found 2: AServiceImpl1,AServiceImpl2
预期单个bean匹配,但是发现了两个
案例代码
服务接口
package com.wcf.demo08;
public interface IAService {
void show();
}
服务接口实现类
package com.wcf.demo08;
import org.springframework.stereotype.Service;
@Service
public class AServiceImpl1 implements IAService {
@Override
public void show() {
System.out.println("调用了AServiceImpl1的show方法");
}
}
package com.wcf.demo08;
import org.springframework.stereotype.Service;
@Service
public class AServiceImpl2 implements IAService {
@Override
public void show() {
System.out.println("调用了AServiceImpl2的show方法");
}
}
Java配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {"com.wcf.demo08"})
public class JavaConfig {
}
测试
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
IAService bean = applicationContext.getBean(IAService.class);
bean.show();
}
}
问题出现的原因
以上同一类型的对象在IOC容器当中有两个,这个时候如果我们仅仅只是通过类型来查找,那么就会报错
解决方案
方案一
通过组合条件查找,通过类型+bean名字的方式
代码
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
IAService bean = applicationContext.getBean("AServiceImpl1", IAService.class);
bean.show();
}
}
测试
运行结果:
调用了AServiceImpl1的show方法
补充
在AServiceImpl1和AServiceImpl2实现类上,我们只是添加了@Service
注解,并没有显示的指定实现类在IOC容器中的bean的名称(被IOC容器管理的类就称之为是一个bean),默认的名字就是类名
也可以查看被IOC容器管理的类型叫啥玩意
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
String[] beanNamesForType = applicationContext.getBeanNamesForType(IAService.class);
Arrays.stream(beanNamesForType).forEach(System.out::println);
}
}
运行结果:
AServiceImpl1
AServiceImpl2
方案二
使用@Primary,当自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者
代码
在AServiceImpl1类上加@Primary注解
package com.wcf.demo08;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
@Service
@Primary
public class AServiceImpl1 implements IAService {
@Override
public void show() {
System.out.println("调用了AServiceImpl1的show方法");
}
}
测试
package com.wcf.demo08;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
IAService bean = applicationContext.getBean(IAService.class);
bean.show();
}
}
运行结果
调用了AServiceImpl2的show方法