澄澈的眼|这Spring注入对象处理过程也太细了,收藏了,什么神仙

1、自动装配与@Autowired这里首先做一个区分 , 因为在之前的很长一段时间内 , 我都错误的以为@Autowired就是自动装配 。 这也就引发了我一直错误的任务Spring的自动装配首先是byType然后是byName的 。 通过这段时间对于源码的阅读 , 我才意识到这个错误 。
当涉及到自动装配Bean的依赖关系时 , Spring提供了4种自动装配策略 。
publicinterfaceAutowireCapableBeanFactory{//无需自动装配intAUTOWIRE_NO=0;//按名称自动装配bean属性intAUTOWIRE_BY_NAME=1;//按类型自动装配bean属性intAUTOWIRE_BY_TYPE=2;//按构造器自动装配intAUTOWIRE_CONSTRUCTOR=3;//过时方法 , Spring3.0之后不再支持@DeprecatedintAUTOWIRE_AUTODETECT=4;...}1.1自动装配
在xml中定义Bean的时候 , 可以通过如下的方式指定自动装配的类型 。
如果使用了根据类型来自动装配 , 那么在IOC容器中只能有一个这样的类型 , 否则就会报错!
1.2使用注解来实现自动装配
@Autowired注解 , 它可以对类成员变量、方法及构造函数进行标注 , 完成自动装配的工作 。 Spring是通过@Autowired来实现自动装配的 。 当然 , Spring还支持其他的方式来实现自动装配 , 如:「JSR-330的@Inject注解」、「JSR-250的@Resource注解」 。
通过注解的方式来自动装配Bean的属性 , 它允许更细粒度的自动装配 , 我们可以选择性的标注某一个属性来对其应用自动装配 。
2、依赖注入在这篇文章中 , 我将详细的分析 , 在一个对象中通过@Autowired注入或@Resource注入属性的处理过程 。 这里我还是采取使用情形 , 然后画出简要流程图 , 最后再是源码分析的方式来介绍本文所要涉及的知识点 。
2.1日常开发中注入对象的方式
「情形一」:通过@Autowired注解对象的方式
@ServicepublicclassDemoServiceTwo{@AutowiredDemoServiceThreedemoServiceThree;}「情形二」:通过@Autowired注解构造器的方式
@ServicepublicclassDemoServiceTwo{DemoServiceOnedemoServiceOne;@AutowiredpublicDemoServiceTwo(DemoServiceOnedemoServiceOne){this.demoServiceOne=demoServiceOne;}}「情形三」:通过@Resource注解对象的方式
@ServicepublicclassDemoServiceTwo{@ResourceDemoServiceOnedemoServiceOne;}「情形四」:通过@Autowired注解方法的方式
@ServicepublicclassDemoServiceTwo{DemoServiceOnedemoServiceOne;@Autowiredpublicvoidprepare(DemoServiceOnedemoServiceOne){this.demoServiceOne=demoServiceOne;}}上述的四种方式是我们在日常开发中经常用到的注入对象的方式 。 这四种方式 , 在Spring对应不同的处理逻辑 。
2.2对象之间依赖关系处理流程
上图中描述了前面「2.1」中所介绍的四种情形的处理 , 其中蓝色线条所表示的是@Resource注解的处理过程 。 红色线条表示@Autowired注解的处理过程 , 与之对应的有拆分成三种子情况AutowiredFieldElement表示注解属性的情况AutowiredMethodElement表示注解方法的情况绿颜色的线条表示注解在构造方法上的情况通过上述流程图 , 我从中找到了以下几点 。 通过以下几点我们也可以区分@Resource和@Autowired 。
两种注解的处理方式都是通过后置处理器来完成处理的 , getBeanPostProcessors()在我们不做任何扩展的情况下 , Spring中只有五个 。 如有忘记请查看:「容器初始化先发五虎」;对于@Resource的处理是通过CommonAnnotationBeanPostProcessor来完成的 。 对于@Autowired的处理是通过AutowiredAnnotationBeanPostProcessor来处理的 。 对于@Autowired注解构造器的方式 , 获取到被注解元素为null则直接返回 。 完成populateBean()的过程 。 对于剩下的情形 , 处理思路一致 , 都是先获取到被注入的对象 , 然后将维护对象属性之间的关系 。 重点突出一下getBean()这里还是我们熟悉的getBean()...field.set()维护对象之间的依赖关系 。 3、源码分析源码分析首当其冲的就是方法入口 , 在对象的包装BeanWrapper创建完成之后 , populateBean()来处理对象之间的依赖关系: