Spring源码阅读后的自我理解(给自己看的)

前言

Spring本质是一个bean工厂(beanFactory),它能按照我们的要求生产各种各样的bean,但是在生产过程中需要解决bean之间的依赖关系,引入了DI(依赖注入)。它能帮我们把bean之间做到松耦合,同时在生产bean的各个阶段对bean做额外的处理,Spring将这些阶段通过接口暴露给我们,只要我们让bean实现对应的接口,那么Spring就会在bean生命周期对应的阶段调用对应接口中的方法来处理该bean。

BeanFactory继承结构

在这里插入图片描述

  1. 四层接口
    第一层接口:
    BeanFactory,主要是getBean()方法
    第二层接口:
    HierarchicalBeanFactory,是为了实现bean工厂的层级关系提供支持。
    AutowireCapableBeanFactory,提供自动装配bean能力的功能支持。
    ListableBeanFactory,可以枚举所有的bean实例,是为了使客户端访问工厂中的bean而设计的。
    第三层接口:
    ConfigurableBeanFactory,继承HierarchicalBeanFactory并对它做了增强,还继承了另一个外来的接 口 SingletonBeanRegistry。
    第四层接口:
    ConfigurableListableBeanFactory,继承了ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory,功能强大
  2. 三个实现类
    1、AbstractBeanFactory:
    继承了DefaultSingletonBeanRegistry,实现了ConfigurableListableBeanFactory接口,重写了getBean()方法,并在里面定义了两个个抽象方法getBeanDefinition()、createBean()
    2、AbstractAutowireCapableBeanFactory:
    继承了AbstractBeanFactory并且实现了AutowireCapableBeanFactory接口,实现了上面的抽象方法createBean(),里面主要是三个方法,bean的实例化-createBeanInstance()、bean的属性注入-populateBean()、bean的初始化-initializeBean()。
    3、DefaultListableBeanFactory:
    继承了AbstractAutowireCapableBeanFactory,同时实现了ConfigurableListableBeanFactory接口、BeanDefinitionRegistry接口。实现了上面的抽象方法getBeanDefinition(),其实也就是重写BeanDefinitionRegistry接口中的方法。它拥有这个继承体系中的所有功能。
  3. 两个外来接口
    1、BeanDefinitionRegistry:
    提供了对BeanDefinition的操作功能,比如注册、获取、移除等,实现类是DefaultListableBeanFactory。
    2、SingletonBeanRegistry:
    提供对单例bean的操作功能,比如注册、获取等,实现类是DefaultSingletonBeanRegistry。
bean的生命周期
  • 容器的启动阶段
    1、读取bean的xml,将xml文件中的每一个元素分别转换成一个BeanDefinition对象。
    2、通过BeanDefinitionRegistry将这些bean注册到beanFactory中。
    3、调用BeanFactoryPostProcessor接口的postProcessBeanFactory()方法。比如:PropertyPlaceholderConfigurer 将占位符替换成properties文件中具体的值。

  • bean生命周期----------对应AbstractAutowireCapableBeanFactory中的doCreateBean()方法;有四个阶段和多个扩展点。
    bean生命周期及扩展点:
    1、实例化-createBeanInstance
    2、属性赋值-populateBean
    3、初始化-initializeBean中的invokeInitMethods方法
    4、销毁-DisposableBean接口的destroy()方法
    第一个扩展点:
    实例化前后会调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation和postProcessAfterInstantiation方法。
    postProcessBeforeInstantiation:在doCreateBean()方法前处理的,如果该方法返回了一个实例对象,则直接返回该bean,用来代替通过内置的实例化流程创建对象。
    postProcessAfterInstantiation:在populateBean()方法最开始处理,如果该方法返回了false,则不会继续进行属性注入。
    第二个扩展点:
    各种Aware标记接口:是在initializeBean()方法最开始处理
    1、首先是BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
    第三个扩展点:
    在初始化前后会调用BeanPostProcessor接口的postProcessBeforeInitialization和postProcessAfterInitialization方法
    这两个处理都是在initializeBean方法中
    第四个扩展点:
    具体的初始化:
    先在postProcessBeforeInitialization方法中会执行@PostConstruct注解的方法
    再执行InitializingBean接口afterPropertiesSet方法,再执行自定义的init-method方法

  • 整体流程:
    1、调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
    2、实例化-createBeanInstance方法
    3、调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法
    5、属性赋值-populateBean方法
    6、Aware标记接口-BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
    7、调用BeanPostProcessor接口的postProcessBeforeInitialization方法(这里会处理@PostConstruct注解)
    8、初始化-initializeBean中的invokeInitMethods方法,先执行InitializingBean接口afterPropertiesSet方法,再执行自定义的init-method方法
    9、调用BeanPostProcessor接口的postProcessAfterInitialization方法(这里会处理@PreDestroy注解)
    10、销毁

  • 关于InitializingBean和DisposableBean
    1、指定初始化方法有很多种,除了实现InitializingBean,还有XML方式,注解方式,没必要记住这几种的执行顺序,一般只会用一种。
    2、DisposableBean类似于InitializingBean,对应生命周期的销毁阶段,以ConfigurableApplicationContext#close()方法作为入口,实现是通过循环取所有实现了DisposableBean接口的Bean然后调用其destroy()方法。

循环依赖

在这里插入图片描述
说明:

  • 实例化完成后需要将对象通过ObjectFactory进行暴露,在ObjectFactory中有一个getObject方法,该方法中是调用了 getEarlyBeanReference 方法对bean做了一些后置处理(SmartInstantiationAwareBeanPostProcessor中的getEarlyBeanReference方法),返回处理完之后的bean。
  • 从三级缓存中获取到ObjectFactory对象后,调用getObject方法(其实就是对bean做后置处理,也就是上述的getEarlyBeanReference 方法)获取提前暴露的bean,然后从三级缓存删除,加入到二级缓存中。
  • bean初始化完成后,会从二级缓存和三级缓存中移除,加入到一级缓存中。
  • 二级缓存和三级缓存的区别:
    二级缓存只需要存储beanName和提前暴露的bean实例的映射关系即可;
    三级缓存还需要对该bean做BeanPostProcessor后置处理。

思考:为什么需要三级缓存来完成呢,感觉二级缓存也能解决循环依赖?

  • 第三级缓存主要是为了代理考虑的,为了AOP考虑的,AbstractAutoProxyCreator 这个类实现了
    SmartInstantiationAwareBeanPostProcessor接口,并且在重写的
    getEarlyBeanReference() 方法中返回了代理对象。
  • 在发生循环依赖的时候,如果不使用三级缓存,我们就必须在A实例化完成后就给A创建代理对象,然后放回二级缓存中;而使用了三级缓存,则会在B中需要注入A的时候从三级缓存中获取A的时候才会给A创建代理对象并返回。这么一看两者确实没什么区别。
  • 如果没有发生循环依赖,没有使用三级缓存时同样的还是会在A完成实例化的时候就给A生成代理对象了,这个和AOP的设计是不符合的;而使用了三级缓存,在对象初始化完成后,这时会调用 getSingleton() 方法,同样的是分别从一级、二级、三级缓存中去获取,此时肯定是在三级缓存中,并且在getObject()方法的时候完成了创建代理对象的过程,也就是说代理的创建是在整个Bean初始化完成之后的。
  • 所以整体来看,这个第三级缓存存在的意义就在于为代理考虑的!
整体流程再梳理:

1、A实例化
将刚实例化完的A通过ObjectFactory进行暴露,放入三级缓存,对A做了一些后置处理(SmartInstantiationAwareBeanPostProcessor)
2、A属性赋值
A中有个属性是B对象,需要获取到B对象,getBean(B)
2.1、B实例化
2.2、B属性赋值
B中有个属性是A对象,需要获取A对象,getBean(A)
从缓存中获取A,此时实际是从3级缓存的ObjectFactory中调用getObject方法来获取bean,获取到之后将A转移到二级缓存中
2.3、B初始化
3、A初始化

BeanFactory和FactoryBean
  • BeanFactory:工厂,是ioc容器的基础。可以管理和创建任意类型的对象。
  • FactoryBean:特殊的Bean,实际返回的对象是重写的 getObject() 方法中返回的对象,一般针对一些复杂bean的创建。如果要获取的是FactoryBean本身的话,getBean()的时候 beanName前面用 ‘&'修饰。
  • 有个经典的FactoryBean例子,就是 SqlSessionFactoryBean,它是mybatis整合Spring中的类。这个类就实现了FactoryBean,重写的getObject()方法中返回的就是 SqlSessionFactory。所以这个时候你获取的就不是 SqlSessionFactoryBean 本身,而是 SqlSessionFactory。同时这个类还实现了 InitializingBean 接口,重写了 afterPropertiesSet() 方法,在该方法中完成了对Mybatis的xml文件解析并得到一个 SqlSessionFactory。
    在这里插入图片描述
BeanFactoryPostProcessor和BeanPostProcessor
  • BeanFactoryPostProcessor:执行时机,在BeanDefinition未被用来创建对象之前,可以针对
    BeanDefinition进行修改。比如PropertyPlaceholderConfigurer,就是用来判断BeanDefinition中是否有${},如果有就根据key去properties文件中获取到具体的value值并替换。
  • BeanPostProcessor:执行时机,在Bean已经被实例化完成、属性赋值完成后,在bean初始化的时候被调用。初始化之前和初始化之后分别执行postProcessBeforeInitialization方法和postProcessAfterInitialization方法。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值