视频链接:马士兵全套Spring源码深度解析:AOP、IOC、Bean生命周期、循环依赖、事务、SpringBoot自动装配等
Spring源码-Spring的基础知识铺垫(P1)
常见面试题:什么是spring?
回答时候以总分两方面层次回答。
总:spring的认知,可上升到boot和clould
分:ioc,aop,ioc如何实现,生命周期,循环依赖
Spring源码-Spring加载注解和配置文件概述(P2)
spring容器中有好多个对象 ,既然是存好的,就会有存取得一套规则,和存储的集合框架
spring使用的一堆map集合做的存储框架
spring怎么知道要创建哪些对象?
- xml形式(过时)
- 注解(@Service,@Controller等)
spring根据这些形式把 bean的定义信息放进BeanDefinition接口中
Spring源码-Spring源码的扩展性(P3)
spring暴露了一个可扩展的接口(BeanDefinitionReader),以后在代码开发中也要注意可扩展 。
接口和抽象类的区别:
接口:自上而下,是一种规范,不考虑具体的实现,实现他的类都要遵循此规范
抽象类:自下而上,把多个类相同特点抽离出来,把共同特点向上抽
Spring源码-Spring的扩展接口-BeanFactorPostProcessor讲解(P4)
获取到定义信息后,通过反射的途径进行创建对象
反射创建对象的步骤:
以配置文件为例,bean的信息会放到BeanDefinition接口中,但是此时还需要放入value值
在获取到bean的信息和创建bean对象之间,还有一步是放入对象value值的操作
这就是PostProcessor,后置增强器,用来提供额外的扩展功能,根据针对的操作对象不同分为BeanFactory和Bean的增强器。
BeanFactory:是一个根接口,相当于创建bean的容器,也是可以直接操作bean的入口。
ApplicationContext是可以获取bean的(ApplicationContext.getBean("beanName")),是因为ApplicationContext是BeanFactory的子类。
而放入Value值,也是对bean的操作
像上图中的占位符解析替换value就可以通过 BeanFactoryPostProcessor中的PlaceholderConfigurerSupport实现
自定义拓展:
可以set值,也可以多个指定@Order
二次开发时候可以用到,一般情况用不到
BeanDefinition到创建bean对象虚线是不存在的,实线是真实的
Spring源码-Spring中模板方法的扩展(P5)
在BeanFactoryPostProcessor纸上还有一个子类, BeanDefinitionRegistryPostProcessor
@ComponentScan,@Import,@ImportResource告诉我们需要哪些额外的对象
xml配置对象早于注解配置对象(@Bean,@Service) 。Spring不是推到重写的而是通过接口进行扩展的就是 BeanDefinitionRegistryPostProcessor。这也是开发代码的思想,多考虑扩展性。
Spring源码-SpringBean生命周期-实例化讲解(P6)
生命周期:从对象的创建到销毁的过程
实例化:在堆空间中申请空间,对象属性值一般是默认值。就是反射创建对象的过程
具体方法名字:creatBeanInstance 反射创建对象(必须牢记)
Spring源码-SpringBean生命周期-初始化属性(P7)
初始化:
- 自定义属性赋值 具体方法名字:populateBean set方法完成赋值操作(必须牢记)
- 容器对象属性赋值 检查aware相关家口并设置依赖
对象的分类
自定义对象属性是私有化的,但是get,set方法是public的,所以容器可以对属性进行赋值。
有些自定义属性可能会包含容器对象。私有化的容器对象也可以增加get,set方法,但是谁去调用?何时调用这些方法呢?所以此时就要有aware接口给一个统一的标识,然后在统一的地方进行处理。
如图:
Spring源码-SpringBean生命周期-bean对象的(P8)
此时的对象理论上是可以使用的了,但是Spring考虑到了扩展性。
扩展操作:
- 执行前置处理方法:使用到的接口BeanPostProcessor中的初始化前的前置处理方法(postProcessAfterInitialization)
- 执行后置处理方法:使用到的接口BeanPostProcessor中的初始化后的后置处理方法(postProcessBeforInitialization)
用处:此处用的比较多的是AOP (此处AOP是狭义上AOP,指的的java中的面向切面编程的实现)
AOP入口:AOP是通过BeanPostProcessor接口实现的,其中有个重要的实现类AbstractAutoProxyCreator。是用来创建proxy对象的,类中的postProcessBeforInitialization方法调用的wrapIfNecessary()中的createProxy(),获取代理对象。
Spring源码-SpringBean生命周期-初始化方法的(P9)
执行初始化方法:使用的方法invokeInitMethods(),检测bean是否实现了InitializingBean接口,实现了接口会要实现一个方法,afterPropertiesSet()方法。
使用bean对象
销毁:一般随着关闭进程而销毁(不会close掉对象的)
方法中可以设置属性,调用方法,添加任意的处理逻辑
总结:
实例化:在堆空间中申请空间,对象属性值一般是默认值。就是反射创建对象的过程
初始化:
- 自定义属性赋值 具体方法名字:populateBean set方法完成赋值操作(必须牢记)
- 容器对象属性赋值 检查aware相关家口并设置依赖
扩展操作:
- 执行前置处理方法:使用到的接口BeanPostProcessor中的初始化前的前置处理方法(postProcessAfterInitialization)
执行初始化方法:使用的方法invokeInitMethods(),检测bean是否实现了InitializingBean接口,实现了接口会要实现一个方法,afterPropertiesSet()方法。
扩展操作:
- 执行后置处理方法:使用到的接口BeanPostProcessor中的初始化后的后置处理方法(postProcessBeforInitialization)
使用bean对象
销毁:一般随着关闭进程而销毁(不会close掉对象的)
Spring源码-源码方法论和整体只是回顾(P10)
学习源码方法论:
- 不要忽略源码中的注释
- 先梳理脉络,再抠细节
- 见名知意
- 大胆猜测,小心验证
- 善用小工具:translate、sequencenDiagram
- 坚持坚持再坚持
- 多画图总结
BeanFactory和FactoryBean的区别
- BeanFactory:并不是指根接口,而是bean对象创建的整体流程,Bean的生命周期是一个完整的标准的流程,相对比很麻烦(流水线)
- FactoryBean:用来创建bean对象,实现FactoryBean<>,就可以做自定义的处理(创建bean时候的私人订制)
- 主要涉及方法:
- isSingleton:判断是否是单例对象
- getObjectType:获取返回对象的类型
- getObject:创建对象
- 主要涉及方法:
Spring源码-循环依赖问题概述(P11)
循环依赖是A类中引用了b对象,而B类中引用了a对象。在bean创建过程中就会导致引用循环,无法创建对象。
解决方式:
- 三级缓存
- 提前暴露对象
Spring源码-图解循环依赖问题(P12)
循环依赖 问题
处理
对对象实例化程度进行分类,分为成品和半成品,把实例化和初始化分开执行。对象实例化后就放进map中,循环依赖情况就把半成品对象放进引用的类中。
Spring源码-循环依赖三级缓存详解(P13)
三级缓存就是三个hashMap结构()
三个map最主要的区别:泛型不同
一级缓存和二级缓存放的是对象,三级缓存泛型是函数式接口
函数式接口:可以将lambda表达式作为参数放到方法的实参中,在方法执行的时候,并不会实际的调用当前lambda表达式,只有在调用getObject方法的时候才会调用lambda表达式
Spring源码-循环依赖debug流程准备(P14)
代码debug观察AB对象的放入缓存的流程
主要debug的类:
Spring源码-循环依赖的debug流程(P15)
看视频