马士兵全套Spring源码深度解析学习

视频链接:马士兵全套Spring源码深度解析:AOP、IOC、Bean生命周期、循环依赖、事务、SpringBoot自动装配等

Spring源码-Spring的基础知识铺垫(P1)

 常见面试题:什么是spring?

回答时候以总分两方面层次回答。

总:spring的认知,可上升到boot和clould

分:ioc,aop,ioc如何实现,生命周期,循环依赖

Spring源码-Spring加载注解和配置文件概述(P2)

 629be0b1e6e34f0982c3f4aa672d0a2a.png

spring容器中有好多个对象 ,既然是存好的,就会有存取得一套规则,和存储的集合框架

spring使用的一堆map集合做的存储框架

spring怎么知道要创建哪些对象?

5eca8a06d9a440adba519e6c0ee859fb.png

  • xml形式(过时)
  • 注解(@Service,@Controller等) 

d561676746e24b959daabc0a458ec17c.png

spring根据这些形式把 bean的定义信息放进BeanDefinition接口中

Spring源码-Spring源码的扩展性(P3)

 eb2272ee9daa4fecb72a79b1bd508c9b.png

spring暴露了一个可扩展的接口(BeanDefinitionReader),以后在代码开发中也要注意可扩展 。

接口和抽象类的区别:

接口:自上而下,是一种规范,不考虑具体的实现,实现他的类都要遵循此规范

抽象类:自下而上,把多个类相同特点抽离出来,把共同特点向上抽

Spring源码-Spring的扩展接口-BeanFactorPostProcessor讲解(P4)

6d19d6f5557c45b5a0cba8eb725ce427.png

获取到定义信息后,通过反射的途径进行创建对象

反射创建对象的步骤: 

aaf7a19113114361b5471925ef97f103.png

 以配置文件为例,bean的信息会放到BeanDefinition接口中,但是此时还需要放入value值

4d66e8cff08e40648487e8b17fbfe65b.png

 在获取到bean的信息和创建bean对象之间,还有一步是放入对象value值的操作

这就是PostProcessor,后置增强器,用来提供额外的扩展功能,根据针对的操作对象不同分为BeanFactory和Bean的增强器。

BeanFactory:是一个根接口,相当于创建bean的容器,也是可以直接操作bean的入口。

ApplicationContext是可以获取bean的(ApplicationContext.getBean("beanName")),是因为ApplicationContext是BeanFactory的子类。

 而放入Value值,也是对bean的操作

a18d8b794b2b4eaa8296ee5578855fd4.png像上图中的占位符解析替换value就可以通过 BeanFactoryPostProcessor中的PlaceholderConfigurerSupport实现

 自定义拓展:

可以set值,也可以多个指定@Order

03ca306907f14d8cbdffcb0ff7261807.png

90674ccd98db4f0b9927b4f7f35005e4.png

二次开发时候可以用到,一般情况用不到

BeanDefinition到创建bean对象虚线是不存在的,实线是真实的

Spring源码-Spring中模板方法的扩展(P5)

 在BeanFactoryPostProcessor纸上还有一个子类, BeanDefinitionRegistryPostProcessor

e2919e90a59c46dabf899c367c39904a.png

@ComponentScan,@Import,@ImportResource告诉我们需要哪些额外的对象

xml配置对象早于注解配置对象(@Bean,@Service) 。Spring不是推到重写的而是通过接口进行扩展的就是 BeanDefinitionRegistryPostProcessor。这也是开发代码的思想,多考虑扩展性。

Spring源码-SpringBean生命周期-实例化讲解(P6)

生命周期:从对象的创建到销毁的过程 

933264babd794da7b786af510023b5b0.png

实例化:在堆空间中申请空间,对象属性值一般是默认值。就是反射创建对象的过程

具体方法名字:creatBeanInstance  反射创建对象(必须牢记)

Spring源码-SpringBean生命周期-初始化属性(P7)

初始化:

  • 自定义属性赋值     具体方法名字:populateBean  set方法完成赋值操作(必须牢记)
  • 容器对象属性赋值     检查aware相关家口并设置依赖

对象的分类

909589ae771f4b3ead113c7c60c27ee5.png

 自定义对象属性是私有化的,但是get,set方法是public的,所以容器可以对属性进行赋值。

有些自定义属性可能会包含容器对象。私有化的容器对象也可以增加get,set方法,但是谁去调用?何时调用这些方法呢?所以此时就要有aware接口给一个统一的标识,然后在统一的地方进行处理。

如图:

7ac3473fd2a4435a8c972e0597c9a452.png

fa773b699ad54144b07057b412e29ee2.png

Spring源码-SpringBean生命周期-bean对象的(P8)

 6ee6425010554c38a365ebffb3823c82.png

此时的对象理论上是可以使用的了,但是Spring考虑到了扩展性。

扩展操作:

  • 执行前置处理方法:使用到的接口BeanPostProcessor中的初始化前的前置处理方法(postProcessAfterInitialization)
  • 执行后置处理方法:使用到的接口BeanPostProcessor中的初始化后的后置处理方法(postProcessBeforInitialization)

用处:此处用的比较多的是AOP (此处AOP是狭义上AOP,指的的java中的面向切面编程的实现)

AOP入口:AOP是通过BeanPostProcessor接口实现的,其中有个重要的实现类AbstractAutoProxyCreator。是用来创建proxy对象的,类中的postProcessBeforInitialization方法调用的wrapIfNecessary()中的createProxy(),获取代理对象。

b57044d8ed5b4feea200b763d41327a4.png

Spring源码-SpringBean生命周期-初始化方法的(P9)

c19a691ad8714f3eaadd5b94d8b3fc91.png

 执行初始化方法:使用的方法invokeInitMethods(),检测bean是否实现了InitializingBean接口,实现了接口会要实现一个方法,afterPropertiesSet()方法。

使用bean对象

销毁:一般随着关闭进程而销毁(不会close掉对象的)

方法中可以设置属性,调用方法,添加任意的处理逻辑

3805a3fdc0a54d80a34d3652118be765.png

总结: 

534bacafee87491c9d1d2e5c6329c4c1.png

实例化:在堆空间中申请空间,对象属性值一般是默认值。就是反射创建对象的过程

初始化:

  • 自定义属性赋值     具体方法名字:populateBean  set方法完成赋值操作(必须牢记)
  • 容器对象属性赋值     检查aware相关家口并设置依赖

扩展操作:

  • 执行前置处理方法:使用到的接口BeanPostProcessor中的初始化前的前置处理方法(postProcessAfterInitialization)

 执行初始化方法:使用的方法invokeInitMethods(),检测bean是否实现了InitializingBean接口,实现了接口会要实现一个方法,afterPropertiesSet()方法。

扩展操作:

  • 执行后置处理方法:使用到的接口BeanPostProcessor中的初始化后的后置处理方法(postProcessBeforInitialization)

使用bean对象

销毁:一般随着关闭进程而销毁(不会close掉对象的)

Spring源码-源码方法论和整体只是回顾(P10)

 学习源码方法论:

  1. 不要忽略源码中的注释
  2. 先梳理脉络,再抠细节
  3. 见名知意
  4. 大胆猜测,小心验证
  5. 善用小工具:translate、sequencenDiagram
  6. 坚持坚持再坚持
  7. 多画图总结

BeanFactory和FactoryBean的区别

  • BeanFactory:并不是指根接口,而是bean对象创建的整体流程,Bean的生命周期是一个完整的标准的流程,相对比很麻烦(流水线)
  • FactoryBean:用来创建bean对象,实现FactoryBean<>,就可以做自定义的处理(创建bean时候的私人订制)
    • 主要涉及方法:
      • isSingleton:判断是否是单例对象
      • getObjectType:获取返回对象的类型
      • getObject:创建对象

Spring源码-循环依赖问题概述(P11)

 循环依赖是A类中引用了b对象,而B类中引用了a对象。在bean创建过程中就会导致引用循环,无法创建对象。

1d57d8dabb1a45d58bd883a10ea1b665.png

解决方式:

  • 三级缓存
  • 提前暴露对象

Spring源码-图解循环依赖问题(P12)

循环依赖 问题

 1286453f2f7e40289b68fef05096c758.png

 处理

对对象实例化程度进行分类,分为成品和半成品,把实例化和初始化分开执行。对象实例化后就放进map中,循环依赖情况就把半成品对象放进引用的类中。

bf7cbe139bef46b99e25ecc984839d70.png

Spring源码-循环依赖三级缓存详解(P13)

三级缓存就是三个hashMap结构() 

3154125ea44d40f49deca27bf58597d7.png

 三个map最主要的区别:泛型不同

一级缓存和二级缓存放的是对象,三级缓存泛型是函数式接口

函数式接口:可以将lambda表达式作为参数放到方法的实参中,在方法执行的时候,并不会实际的调用当前lambda表达式,只有在调用getObject方法的时候才会调用lambda表达式

Spring源码-循环依赖debug流程准备(P14)

 代码debug观察AB对象的放入缓存的流程

主要debug的类:

d9bdb30324ea42a990144ad4e96b19ea.png

Spring源码-循环依赖的debug流程(P15)

 看视频

Spring源码-循环依赖问题的思考(P16)

1ec8c66250f4430c8e157c8f64a0912b.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值