问题:

1.springBoot 类 BService 继承 类 AService ,在写CLassA单元测试的时候

如果写成

@Autowired
private AService service;
或者写成:

@Autowired
private AService wefsd;  //一个乱七八糟的字符组成

启动容器的时候会报错,显示:

NoUniqueBeanDefinitionException , X.X.X.XAService这个bean,发现了两个一个是 aService,一个是bService,

 

分析:

@Autowired 默认按照类型加载,如果存在多个类型相同的bean,类似这种父子关系,导致无法确认唯一结果的时候,会接着按照名称查找,我本来以为这个名称指的是bean的默认名字(目前案例中没有显示指定),但是这个默认名字和我自定的变量名有什么关系呢,我的理解是 默认bean名字是 类名首字母小写(aService),我恰好定义的变量名称(service,wefsd,)不相同,此时报错,推测原因是 容器平台把这个变量名称定义为bean名称,发现按照名称也找不到,所以报错,如果我写成下面的这个:

@Autowired
private AService aService;

就不会报错了,这个时候,bean名称默认就是变量名称。。。待定

 

//=============================第二次测试如下 ==========================================

父子类如下:

@Service
@Slf4j
public class ParentService {

    void parentPrint() {
        log.info("this is ParentService parentPrint function");
    }

}


@Service
@Slf4j
public class ChildService extends ParentService {

    void childPrint() {
        log.info("this is ChildService childPrint function");
    }

}

子类测试1 :private ChildService childService;

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class ChildServiceTest1 {

    @Autowired
    private ChildService childService;

    @Test
    public void test(){
        childService.childPrint();
    }

}

结果显示正常

子类测试2:private ChildService sssss;

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class ChildServiceTest2 {

    @Autowired
    private ChildService sssss;

    @Test
    public void test(){
        sssss.childPrint();
    }
}

结果显示正常

父类测试1 :private ParentService parentService;

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class ParentServiceTest1 {

    @Autowired
    private ParentService parentService;

    @Test
    public void test(){
        parentService.parentPrint();
    }
}

结果显示正常

父类测试2 : private ParentService ssss;

ExtendWith(SpringExtension.class)
@SpringBootTest
@Slf4j
public class ParentServiceTest2 {

    @Autowired
    private ParentService ssss;

    @Test
    public void test(){
        ssss.parentPrint();
    }
}

结果异常



org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.example.demo.test1.service.ParentServiceTest2': Unsatisfied dependency expressed through field 'ssss'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.demo.test1.service.ParentService' available: expected single matching bean but found 2: childService,parentService

	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
	

 

日志里面显示:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.example.demo.test1.service.ParentServiceTest2': Unsatisfied dependency expressed through field 'ssss'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.demo.test1.service.ParentService' available: expected single matching bean but found 2: childService,parentService

 

首先,我们知道 @Autowired 默认按照类型装配,如果类型不能唯一确定那么就按照名称装配

根据 上面四个实验可以得出结论:

1. 子类注入的时候是按照类型选择的,否则 子类测试2实验应该就会失败,也就是说在注入子类的时候,根据类型就可以唯一确认,子类是特殊的父类,这个应该没问题;

2.父类是按照名称装配的,否则父类测试2 不应该报错,相对来说,父类较为宽泛,所以注入父类会发现有两个bean,那么这个时候就会开始按照名称查找,这个名称spring会把变量名作为bean名称来查询,这也就是父类测试2失败以及父类测试1成功的的原因了。

3.补充:@Resource 按照名称查找,这个名称就是变量名称。

 

 

 

 

 

 

 

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐