【Spring源码系列- IOC】
进入方法autowireByType()
首先获取工厂的自定义类型转换器,如果获取到没有配置自定义类型转换器就使用bw作为类型转换器
插播:为什么类型为BeanWrapper的bw可以赋值给类型为TypeConverter的converter?
因为BeanWrapper继承了ConfigurablePropertyAccessor,而ConfigurablePropertyAccessor继承了TypeConverter
定义一个集合用于存放所有候选Bean的Name,接下来的unsatisfiedNonSimpleProperties()方法和autowiredByName()中的一样用于筛选属性(即同时满足有写入属性方法 && 未被排除在依赖检查项之外 && pvs中没有该pd的属性名 && 该pd的属性类型不是“简单类型”)
接下来同样的,遍历属性名数组,先从bw中获取propertyName对应的PropertyDescriptor
判断bean对象是否是PriorityOrder实例,并根据结果给eager赋值,eager为true时会导致初始化Lazy-init单例和由FactoryBeans(或带有”factory-bean”引用的工厂方法)创建的对象以进行类型检查
随后将methodParam封装成AutowireByTypeDependencyDescriptor并赋值给desc,通过调用resolveDependency()方法,根据desc的依赖类型解析出与descriptor所包装的对象匹配的候选Bean对象,紧接着判断获取到的对象autowiredArgument是否为空,不为空则将当前遍历到的propertyName和刚获取到的autowiredArgument对象分别作为键、值添加进pvs
最后像上面autowireByName()方法一样,遍历所有候选BeanNames,依次注册propertyName、beanName的依赖关系
我们在上一篇文章分析过autowireByName()方法(【自动注入·名称】autowireByName()详解 ),将autowireByType()和autowireByName()这两个方法做下对比,可以发现整体流程大致相同,都是一个for♻️循环遍历经过unsatisfiedNonSimpleProperties()方法筛选过的propertyNames,而且都有将符合要求的propertyName和根据propertyName获取到对象作为键值对放入pvs,并调用方法registerDependentBean()进行autowiredBeanName、beanName依赖关系的注册,但是主要有以下几点区别:
-
根据propertyName获取到对象不同
-
autowireByName()是通过getBean(propertyName)获取到对象
-
autowireByType()是通过resolveDependency(desc, beanName, autowiredBeanNames, converter)获取到对象
-
调用方法registerDependentBean()进行注册遍历的对象不同
-
autowireByName()注册的是propertyName、beanName的依赖关系
-
autowireByType()注册的是autowiredBeanName、beanName的依赖关系
而autowiredBeanName是从集合autowiredBeanNames中依次获取的,而autowiredBeanNames是方法autowireByType()在一开始定义了一个空的集合(下图1️⃣处)
那么问题来了:autowiredBeanNames是在哪里被赋值的呢?
从上图我们可以看到,autowiredBeanNames在1️⃣处被定义成了一个空集合,在2️⃣处作为参数传入方法resolveDependency()中,3️⃣处被遍历,4️⃣处清空,所以autowiredBeanNames中的值只能是在方法resolveDependency()中被添加的
resolveDependency()
进入方法resolveDependency()
选择一个他的实现类,我这里选的是DefaultListableBeanFactory(emmm…好像也没啥别的可选)
可以看到autowiredBeanNames传入了方法doResolveDependency()中
doResolveDependency()
进入方法doResolveDependency()
此方法是用于解descriptor所包装的对象匹配的候选bean对象,有几段逻辑值得分析分析
获取descriptor的依赖类型,并尝试使用descriptor的默认值作为最近候选的Bean对象
随后使用此BeanFactory的自动装配候选解析器获取descriptor的默认值,如果该值不为空则继续判断是否为String类型,是的话则进行解析(如果是表达式则会进一步进行解析),在获取beanName的合并后的RootBeanDefinition,随后评估该bd中包含的value,如果刚刚解析出来的strVal是一个表达式,则会再对其进行解析
接着判断传入的参数typeConverter是否为空,如果为空就调用getTypeConverter()方法获取工厂的类型转换器,最后返回将value转换为type的实例对象
如果上面的过程未return,则会尝试针对desciptor所包装的对象类型是(stream、数组、Collection类型且对象类型是接口、Map)的情况进行解析与依赖类型匹配的候选Bean对象,并将其封装成相应的依赖类型对象,通过resolveMultipleBean()方法获取multipleBeans,如果获取到的multipleBeans不为空则将其返回
可以看到autowiredBeanNames传入了方法resolveMultipleBeans()中
resolveMultipleBeans()
进入resolveMultipleBeans()方法
看(*≧ω≦)~autowiredBeanNames就是在方法resolveMultipleBean()中被赋值的
我们再回到再回到doResolveDependency()方法中
接下来的逻辑是尝试获取与type匹配的唯一候选bean对象,查找与type匹配的候选bean对象,构建成Map<beanName,Bean对象>,如果构建的Map对象为空,则继续判断descriptor是否需要注入,如果需要则抛出异常,不需要则返回空表示未找到候选的bean对象
在确定Map<beanName,Bean对象>不为空后,分别定义了用于存放候选的beanName和候选bean对象的两个变量autowiredBeanName和instanceCandidate,接下来是通过一个if判断分支为这两个变量赋值:
-
如果候选bean对象的Map<String, Object>不止一个,那就需要从中确定一个可以自动注入的最佳的beanName赋值给autowiredBeanName,如果没获取到这样的beanName,并且descriptor是需要注入/type不是数组或者集合类型,则让descriptor尝试选择一个实例(默认返回NoUniqueBeanDefinitionException异常)最后根据获取的autowiredBeanName从matchingBeans中获取bean对象,赋值给instanceCandidate
-
如果候选bean对象的Map<String, Object>只有一个的话,尝试获取该唯一值(map为空的时候已经在前面抛出异常或者返回了),随后分别将键、值赋给autowiredBeanName和instanceCandidate
最后返回获取到的bean对象
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135366.html