Spring源码分析:@Autowired注解原理分析

前言

关于@Autowired这个注解,咱们再熟悉不过了,常常跟@Resource来作对比,这篇文章咱们不讨论二者有何异同,仅分析@Autowired的原理(基于Spring5)。java

问题

假如一个接口(IUserService)有两个实现类,分别是(UserServiceImpl01)和(UserServiceImpl02),在咱们给类注入的时候,这样写(@Autowired private IUserService userService)会发生什么状况?答案确定是报错,那么原理呢?文字描述:由于首先@Autowired是按照类型注入的,也就是.class,但UserServiceImpl01和UserServiceImpl02都是IUserService类型的,因而Spring就会按照后面的名字(userService)在容器中查找,但发现根本没有这个名字,由于两个实现类在不指定名字状况下,就是首字母小写的类名,而后抛出异常:expected single matching bean but found 2。。。app

如何解决这类问题

  1. 若是有两个实现类,还要使用@Autowired注解,能够将userService改为咱们指定的实现类名称,好比UserServiceImpl01,或者不想改userService,能够加@Qualifier(value = "userServiceImpl01"),指定须要注入的实现类。
  2. 使用@Resource注解,手动指定实现类名称。

还有不少种方法,但基本思想都同样,无非就是如何区分两个同祖宗的儿子,既然根儿相同,那就只有指定名字了。源码分析

@Autowired原理

提到@Autowired咱们通常都知道叫依赖注入post

  1. 什么是依赖注入?
  2. 什么是注入,注到哪里?
  3. 何时注入的?

什么是依赖注入?

依赖注入:Dependency Injection,简称DI,说白了就是利用反射机制为类的属性赋值的操做。this

什么是注入,注入到哪里?

注入就是为某个对象的外部资源赋值,注入某个对象所须要的外部资源(包括对象、资源、常量数据等)。IOC容器注入应用程序某个对象,应用程序所依赖的对象。spa

何时注入的?

在完成对象的建立,为对象变量进行赋值的时候进行注入(populate)。debug

源码分析

  1. 首先点开@Autowired,注释上写Please consult the javadoc for the AutowiredAnnotationBeanPostProcessor,让咱们去查阅这个类,看一下这个类的继承关系树,以下:

请输入图片描述
可见它间接实现InstantiationAwareBeanPostProcessor,就具有了实例化先后(而不是初始化先后)管理对象的能力,实现了BeanPostProcessor,具备初始化先后管理对象的能力,实现BeanFactoryAware,具有随时拿到BeanFactory的能力,也就是说,这个AutowiredAnnotationBeanPostProcessor具有一切后置处理器的能力。对象

  1. 容器在初始化的时候,后置处理器的初始化要优先于剩下自定义Bean(好比咱们自定义的Service,Controller等等)的初始化的,咱们自定义的Bean初始化是在finishBeanFactoryInitialization(beanFactory)这里完成的,来到AbstractApplicationContext的refresh()方法。
  2. finishBeanFactoryInitialization(beanFactory)-->beanFactory.preInstantiateSingletons()-->getBean(beanName)-->doGetBean(beanName)-->来到AbstractBeanFactory第317行createBean(beanName, mbd, args),来建立bean实例-->来到AbstractAutowireCapableBeanFactory第503行doCreateBean(beanName, mbdToUse, args)-->紧接着来到AbstractAutowireCapableBeanFactory的第543行,instanceWrapper = createBeanInstance(beanName, mbd, args)就已经把Bean实例建立出来了,只不过instanceWrapper是一个被包装过了的bean,它里面的属性还未赋实际值-->而后来到第555行applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName),这一步的做用就是将全部的后置处理器拿出来,而且把名字叫beanName的类中的变量都封装到InjectionMetadata的injectedElements集合里面,目的是之后从中获取,挨个建立实例,经过反射注入到相应类中。

请输入图片描述

  1. 紧接着来到AbstractAutowireCapableBeanFactory第588行populateBean(beanName, mbd, instanceWrapper)-->点进去,来到AbstractAutowireCapableBeanFactory的第1347行,来循环遍历全部的后置处理器for (BeanPostProcessor bp : getBeanPostProcessors()),从方法名字postProcessPropertyValues也能看出来,就是给属性赋值,当bp是AutowiredAnnotationBeanPostProcessor的时候,进入postProcessPropertyValues方法,来到AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法,以下:

请输入图片描述
首先找到须要注入的哪些元数据,而后metadata.inject(注入),注入方法点进去,来到InjectionMetadata的inject方法,在一个for循环里面依次执行element.inject(target, beanName, pvs),来对属性进行注入。blog

  1. 进入element.inject(target, beanName, pvs),注意,这里必需要debug才能够进入真正的方法。来到AutowiredAnnotationBeanPostProcessor的inject方法,

第584行,value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter),由工厂解析这个依赖,进入,来到DefaultListableBeanFactory第1065行,result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter)再次解析依赖,点击进入,来到DefaultListableBeanFactory的doResolveDependency()方法,前面是一堆判断,比较,查看属性类型,这种类型的有几个(matchingBeans),若是只有一个匹配,那么来到第1138行,instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this),进入这个方法,能够看到就是前面说的根据工厂来建立实例的过程了:beanFactory.getBean(beanName),其中这个beanName就是属性的名称,当通过一系列操做完成属性的实例化后,便来到AutowiredAnnotationBeanPostProcessor的第611行,利用反射为此对象赋值。这样,对象的建立以及赋值就完成了。继承

总结

在容器启动,为对象赋值的时候,遇到@Autowired注解,会用后置处理器机制,来建立属性的实例,而后再利用反射机制,将实例化好的属性,赋值给对象上,这就是Autowired的原理。

相关文章
相关标签/搜索