浅谈spring生命周期

Spring源码笔记

Spring, 意为春天

个人博客:kana.chat:90

IOC:

IOC,意为控制反转(Inversion of Control),可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

spring装载流程——IOC的实现:
图片示例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p7YF9UFE-1602049275471)(https://kana-bucket.oss-cn-beijing.aliyuncs.com/%E5%9B%BE%E7%89%87_1598250098239.png)]

1.scan扫描包,扫描类BeanFactoryPostProcessor(spring内部的BeanFactoryPostProcessor子类),包装为BeanDefinition,然后放入 BeanDefinitionMap
2. 执行BeanFactoryPostProcessor(spring内部的BeanFactoryPostProcessor与程序员提供的,直接实现该接口的对象)
------->遍历map
3.validate 验证该bean能否实例化,是否需要实例化,实例化之前需要做什么
4.得到类的class对象
5.推断类的构造方法
6.反射 实例化该类
7.合并beanDefinition
8.提前暴露一个bean工厂对象
9.填充属性–自动注入
10.—部分aware接口
11.执行 --另外部分aware接口 执行spring生命周期回调方法—anno(注解的)
12.执行接口版本的aware方法
13.beanPostprocessor的前置方法–aop
14.put 单例池

bean在注册后写入注册表(读取配置文件或者注解),根据注册表实例化,之后放入缓存池等待应用程序使用(ConcurrentHashmap)。

ioc的实现:
BeanFactory是最基础的框架设施,面向spring本身,而开发者一般是使用拓展了许多功能的ApplicationContext来获取bean并且使用其他功能。

  在普通的java方法中,执行psvm方法,启动jvm将编译好的代码从磁盘读入内存,然后写入永久代并且执行,对象放入堆栈。

  但spring启动后,对应扫描到的包将磁盘上的.class对象封装成一个BeanDefinition对象(包含许多bean的信息,如:是否懒加载,是否需要初始化,beanName),封装完之后若有自定义的BeanFactoryPostProcessor,则去执行改变BeanDefinition的一些属性。若通过验证则实例化放入单例缓存池(单例),
浅谈spring生命周期_第1张图片

  spring的bean工厂(BeanFactory,顶层接口)默认即为DefaultListableBeanFactory类,该类的beanDefinitionMap 容器 (ConcurrentHashMap)存放了BeanDefinition对象。在invokeBeanFactoryPostProcessors(执行后置处理器)方法中解析扫描的bean,并且将其封装成了BeanDefinition对象(该阶段未实例化)。

图片.png
即是在beanFactory实例化前后可以执行自定义的处理器方法

图片.png
BeanPostProcess,前(后)置处理beanFactory类的接口,而spring有许多内置的实现类,去处理bean工厂,在postProcessBeanFactory方法中依次执行(包含使用者自定义的处理类)。

浅谈spring生命周期_第2张图片

在DefaultListableBeanFactory 中实现了ConfigurableListableBeanFactory的实例化方法,即preinstantlateSingletons()。该类是代码级别的spring Bean工厂,用来实例化bean。
(注:BeanFactory可用于创建丶缓存与查询对象)

重点——循环依赖的解决:

提前暴露bean工厂
spring处理创建单例时有三级缓存,用来解决循环依赖

浅谈spring生命周期_第3张图片

循环依赖三级缓存图片展示 ——

浅谈spring生命周期_第4张图片

实例化对象spring之后进行属性填充,当X填充Y,然后使用getBean获取不到Y之后创建Y,再填充Y中的X时,在singletonObjects一级缓存中得不到X的bean,再从earlySingletonObjects中拿,此时也无X,再从之前提前暴露的singletonFactories工厂中拿取,拿出一个ObjectFactory类型的对象
(这一块使用工厂便于拓展X/Y对象)

浅谈spring生命周期_第5张图片

浅谈spring生命周期_第6张图片

在填充属性时就会将其放入singletonFactories
浅谈spring生命周期_第7张图片

而当上方执行完,将对象放入三级缓存,并且从二级缓存中去除,此时提前暴露一个半成品(未走完bean的生命周期)之后若还有循环依赖(如X与Z互相依赖)则直接取出三级缓存池中的对象。
注:第一次创建X与Y时获取不到,进入不到if体中,因为没有存入singletonsCurrentlyInCreation中,之后就会加入其中。

最后展示下BeanDefinition内部结构:

BeanDefinition:

实例化出来放入singletonObjects的bean与自定义的类无关,与其的BeanDefinition有关
BeanDefinition结构:

浅谈spring生命周期_第8张图片

可以自定义类继承BeanFactoryPostProcessor,拿到BeanDefinition并做出更改(甚至可以更改BeanDefinition里的class类对象,故说类与bean无关)。

题外话:

  spring的话可以看子路老师(业界称之为路神)的源码剖析视频,他可能是国内数一数二的spirng源码剖析讲解者了,无论是spring.framework里面的组件,包括spring生命周期、beanpostprocess后置处理器、beanfactorypostprocess工厂处理器、beanDefinition的merge等等,还是spring.boot的自动装配、零配置、内嵌tomcat,亦或者是spring.cloud alibaba里面的组件和nacos源码,他都有讲解,并且讲解的比较通透。

你可能感兴趣的:(spring,spring,ioc,bean,java)