转载

Spring源码 系列一:配置类的初始化过程

Spring源码 系列一:配置类的初始化过程

前言

趁着假期 && 疫情, 沉淀一下

废话不多说,直奔正题。

Spring的核心,即IOC和AOP,本篇文章其实就是来分析下 Spring 的 IOC 容器,IOC又叫控制反转,把对象以Bean的形式交给IOC去管理,由Spring去管理对象的生命周期,使得Bean与Bean之间的松耦合。

Spring的注解启动类
 
Spring源码 系列一:配置类的初始化过程

进入 AnnotationConfigApplicationContext()

Spring源码 系列一:配置类的初始化过程

这里主要是三个大方法:

this():初始化Spring的相关组件

this.register(annotatedClasses):把我们的配置类注册到IOC

this.refresh():这是个很重要很重要很重的方法!!!重要的事说三遍,后面会细说
复制代码

我们先看 this()方法

Spring源码 系列一:配置类的初始化过程

初始化了一个读取器reader 和 一个扫描器scanner。然后:

Spring源码 系列一:配置类的初始化过程
调用静态方法 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
往容器里注入Spring自带的注解相关的组件(一共是6个),如下:
复制代码
Spring源码 系列一:配置类的初始化过程
this()方法大致就这样,接下来我们来看看 this.register(annotatedClasses)方法
 
Spring源码 系列一:配置类的初始化过程
可以看出,我们的配置类可以传入多个,然后循环注册

继续往下,进入registerBean()
复制代码
Spring源码 系列一:配置类的初始化过程
可以看出,它把我们的配置类封装成了 beanDefinitionHolder

继续往下,进入BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
复制代码
Spring源码 系列一:配置类的初始化过程
继续往下,进入registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
复制代码
Spring源码 系列一:配置类的初始化过程
果断选择 DefaultListableBeanFactory 
复制代码
Spring源码 系列一:配置类的初始化过程
通过上下文断点+分析,程序最后走的是这段方法,即成功把我们的配置类加入到beanDefinitionMap和beanDefinitionNames中去
复制代码

前方高能 refresh()方法

Spring源码 系列一:配置类的初始化过程
一共是12个大方法:本文只做与IOC相关的介绍
复制代码
Spring源码 系列一:配置类的初始化过程
我们关键看 this.invokeBeanFactoryPostProcessors(beanFactory);
复制代码
Spring源码 系列一:配置类的初始化过程
继续往下:
复制代码
Spring源码 系列一:配置类的初始化过程
看源码看关键流程  继续往下:
复制代码
Spring源码 系列一:配置类的初始化过程
Spring前面循环了所有的 BeanDefinition (容器自带的+自己定义的)
然后把自定义的配置类抽离出来,放入 Set<BeanDefinitionHolder> candidates中
然后调用 ConfigurationClassParser解析器去解析自定义的配置 candidates 
继续往下:
复制代码
Spring源码 系列一:配置类的初始化过程
显然是进入这里,不做过多解释 
继续往下:
复制代码
Spring源码 系列一:配置类的初始化过程
判断自定义的配置类 有没有 加ComponentScans注解
如果有加 
继续往下:
复制代码
Spring源码 系列一:配置类的初始化过程
先是得到路径集合basePackages,然后根据excludeFilter进行过滤 
调用扫描器的doScan方法进行扫描
继续往下:
复制代码
Spring源码 系列一:配置类的初始化过程
我们发现其实是一直在进行循环递归处理,直到basePackages循环完
复制代码
解析器解析完了之后,得到一个被解析过的 Set<BeanDefinitionHolder> candidates
调用 this.reader.loadBeanDefinitions(configClasses); 把配置类中与之关联的bean信息注册到容器中去
继续:
复制代码
Spring源码 系列一:配置类的初始化过程
分为了四块
    1.import引入的配置类
    2.内部的包含bean注解的方法
    3.importedResources引入的配置
    4.Registrars引入的配置
    
下面就没啥好看的了,一直在往容器里put就完事
复制代码

总结

Spring的代码算是比较复杂的,引入了大量的组件,以及设计模式,层层嵌套。

当然对我们的提升也是有帮助的,学源码学思想。

下一篇是计划出AOP的博客

后面有时间的话,尽量出一些Spring组件的相关文章,以及自己实现一套IOC以及AOP

热爱可抵岁月漫长,大家相互学习,谢谢。

原文  https://juejin.im/post/5eae9306f265da7bc60e009c
正文到此结束
Loading...