@Autowired 是通过类型查找还是通过属性名查找?

​@Autowired 是通过类型查找还是通过属性名查找?

    前面笔者对@Autowired 的一些重难点做了深入的了解,并对一些关键源码做了深入分析,本节将对@Autowired 的注入方式做详细介绍。

     还是先从案例分析看起:一个User接口

public interface User {}

两个User实现类

@Componentpublic class User2 implements User{}
@Componentpublic class User1 implements User {}

然后再写一个注入类

@Componentpublic class UserTest {  @Autowired  private User user;  @PostConstruct  public void init(){    System.out.println(user);  }}

最后测试类和配置类:

import com.MyImportBeanDefinitionRegistrar;import org.springframework.context.annotation.*;@Configuration@ComponentScan("com")/*@EnableAspectJAutoProxy*//*@Import(MyImportBeanDefinitionRegistrar.class)*/public class AppConfig {}
public class Test {    public static void main(String[] args) {      AnnotationConfigApplicationContext annotationConfigApplicationContext=          new AnnotationConfigApplicationContext(AppConfig.class);          }}

 

然后执行:

十二月 16, 2020 10:29:50 下午 org.springframework.context.support.AbstractApplicationContext refresh警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userTest': Unsatisfied dependency expressed through field 'user'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.User' available: expected single matching bean but found 2: user1,user2Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userTest': Unsatisfied dependency expressed through field 'user'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.User' available: expected single matching bean but found 2: user1,user2  at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:603)  at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)  at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:381)  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1428)  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:603)  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:518)  at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:321)  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:319)  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:848)  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:892)  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:556)  at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:100)  at Test.main(Test.java:21)Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.User' available: expected single matching bean but found 2: user1,user2  at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:221)  at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1234)  at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1176)  at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:600)  ... 14 more

可以看到错误,找不到唯一的User实现类,这里的错误很容易想明白,因为我们实现了两个User类,这里Spring会无法识别具体的那个类作为实现类

,因此就会出现异常,当然这也可以解决,我们可以使用@qualifier注解进行分组,让这个类有唯一表示,这样就能解决冲突,当然我们这里并不是为了解决这个问题,而是想知道@Autowired 到底是通过类型查找还是通过属性名查找?这里笔者先给出答案,先通过类型查找,如果找到了多个实现了在通过名字去对比。下面我们通过源码来证明。

我们直接定位到AutowiredAnnotationBeanPostProcessor这个类,看过笔者前面的文章都知道这个类是干什么的,如果不知道请读者自行查漏补缺

@Autowired 是通过类型查找还是通过属性名查找?

然后我们继续跟踪

@Autowired 是通过类型查找还是通过属性名查找?

一直跟踪

@Autowired 是通过类型查找还是通过属性名查找?

再跟踪

@Autowired 是通过类型查找还是通过属性名查找?

看到这个doResolveDependency方法,点进去

@Autowired 是通过类型查找还是通过属性名查找?

注意看这两个数据,这就是我们在UserTest这个类注入的User属性,此时已经获取了这个类属性,我们继续往下看

@Autowired 是通过类型查找还是通过属性名查找?

还是这个doResolveDependency,我们看到的是Spring是先获取了User接口的所有实现类,我们继续往下看,

@Autowired 是通过类型查找还是通过属性名查找?

相信看到这里,读者一定明白了Spring的注入逻辑了吧,希望看完这篇文章让大家对Spring的源码有更深入的认识。

上一篇:Spring IOC概念及模拟实现


下一篇:【SpringBoot】-Beans自动装配(网址记录)