Spring 源码解析篇都没有贴源码,贴了就太多太长了研究源码时候可能容易看晕,先大致理清楚源码设计编写的总体流程,流程中的几个阶段,而后在细看每个阶段,固然这每个阶段里面可能又是涉及到庞大的代码量,那么又须要将其分为多个阶段,这样一层一层的抽丝剥茧去看不会让本身一上来就产生强烈的挫败感(由于直接去 DEBUG Spring 源码会发现太深了)数组
首先是调用构造器建立 AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner 他们分别是用于处理读取注解 BeanDefinition 和 classPath 路径下的 BeanDefinition 的ide
调用 ClassPathBeanDefinitionScanner 的 doScan 方法开始作扫描工做设计
在 ClassPathScanningCandidateComponentProvider 根据须要扫描的路径调用 GenericApplicationContext 的 getResources 方法,该方法会去递归扫描包路径下面全部的 Class 文件而后将其解析为 Resource 数组返回;就算一个类没有被 @Component 等注解修饰也会加载到 Resource 数组中3d
首先建立 MetadataReader 用于读取 Resource 文件的元数据,主要包括 Resource、 ClassMetadata、AnnotationMetadatacdn
而后判断是否在类上标注了 @Component 等注解,若是标注了进行下一步, 若是只是一个单纯的类则跳过对象
根据 MetadataReader 等信息建立 ScannedGenericBeanDefinition 放入 Set 中,ScannedGenericBeanDefinition 是一个早期 的 BeanDefinition 它目前包含了,类的元数据,Resource 文件,ClassName 等信息,Spring 称 之为 candidates(候选者)blog
遍历这些 candidates,根据其包含的信息作下一步操做;主要包含提取出 Scope 信息,建立 BeanName(通常是将相似 com.xxx.User 全称取类名称小写 beanName = user)递归
而后根据上面获取到的信息去建立一个 BeanDefinitionHolder ,该对象除了持有 BeanDefinition 外存有 beanName 和别名的相关信息get
最后根据 BeanDefinitionHolder 获取到 BeanDefinition 放入到 DefaultListableBeanFactory 的 beanDefinitionMap 中,同时将其 beanName 对应的别名存放在 Map 中源码
关于扫描包加载注解类的步骤为,首先根据定义路径递归遍历其下全部文件将其解析为 Resource 数组。而后遍历 Resource 数组根据其信息建立 ScannedGenericBeanDefinition 这样一个待完善的 BeanDefinition 集合。而后遍历这个集合解析出 Scope、建立 BeanName 解析出别名等信息据此建立出 BeanDefinition。最后将 BeanDefinition 放入容器中同时保存好它的对应别名信息