7000字长文带你深入了解IOC启动原理( 三 )


创建了一个多播器,为添加Listener提供支持 。
主要逻辑:

  • 容器中是否存在applicationEventMulticaster,如果存在直接注册
  • 如果不存在,创建一个SimpleApplicationEventMulticaster,注册到容器中 。
3.3.9 onRefresh()
子类扩展
3.3.10 registerListeners()
观察者模式的实现
7000字长文带你深入了解IOC启动原理

文章插图
 
3.3.11 finishBeanFactoryInitialization
这一部分的内容太多了,所以采用代码和图解的方式来讲解 。

7000字长文带你深入了解IOC启动原理

文章插图
 
下图是创建Bean的主要流程
7000字长文带你深入了解IOC启动原理

文章插图
 
按照图中的序号一个一个说:
  1. BeanDefinition是否需要合并 。BeanDefinition根据不同类型的配置文件信息,会将Bean封装到不同的Bean信息定义类中 。比如我们常用的配置文件版的GenericBeanDefinition;注解扫描版的ScannedGenericBeanDefinition等等 。
而在这个过程中就出现了,父定义和子定义,我们需要在实际处理定义信息的时候进行合并处理,主要有以下三个方面
  • 存在父定义信息,使用父定义信息创建一个RootBeanDefinition,然后将自定义信息作为参数传入 。
  • 不存在父定义信息,并且当前BeanDefinition是RootBeanDefintion类型的,直接返回一份RootBeanDefintion的克隆
  • 不存在父定义信息,并且当前BeanDefintion不是RootBeanDefintiton类型的,直接通过该BeanDefintion构建一个RootBeanDefintion返回
上面的流程也是源码中的执行流程
7000字长文带你深入了解IOC启动原理

文章插图
 
  1. isFactoryBean 。判断是否为FactoryBean
简单介绍一下:FactoryBean是让开发者创建自己需要Bean接口 。内部提供了三个方法
7000字长文带你深入了解IOC启动原理

文章插图
 
当我们通过GetBean直接该Bean的时候,获取到的是该工厂指定返回的Bean类型 。如果想要获取该Bean本身,需要通过一个前缀获得&
7000字长文带你深入了解IOC启动原理

文章插图
 
再来看一个点,这个就是从容器中获取Bean的主要方法,也是解决循环依赖的逻辑
7000字长文带你深入了解IOC启动原理

文章插图
 
来聊一下它是怎么解决循环引用的?
它引入了一个三级缓存的概念
7000字长文带你深入了解IOC启动原理

文章插图
 
在发生循环引用的时候,它首先通过ObejctFactory工厂将Bean创建出来,此时的对象并没有进行属性赋值,仅仅在堆中开辟了空间 。然后将此时的Bean添加到earlySingletonObjects容器里,也就是说这个容器中保存的Bean都是半成品 。而在之后的属性赋值中,由于对象为单例的,所以其引用地址不会发生变化,即对象最终是完整的 。
1.getBean 。通过这个方法直接创建了所有的对象,这也是Spring最核心的方法了,先来看一下它整体的一个流程
7000字长文带你深入了解IOC启动原理

文章插图
 
它的主要逻辑是:
  • 先拿到当前要实例化的Bean的真实名字,主要是为了处理FactoryBean,拿到以后,从当前容器中看是否已经创建过该Bean,如果存在直接返回 。
  • 如果不存在,获取其父工厂,如果父工厂不为空,而且当前容器中不存在当前Bean的信息,则尝试从父工厂中获取Bean定义信息,进行Bean实例化
  • 如果父工厂为空,将当前Bean信息存放到alreadyCreated缓存中 。
  • 获取当前Bean的合并信息(getMergedLocalBeanDefinition),查看当前Bean是否存在依赖,如果存在则判断当前Bean和依赖 Bean 是否为循环依赖,如果不是循环依赖则先创建依赖Bean
  • 判断当前Bean的作用域 。
  • 如果当前Bean是单例对象,直接创建Bean实例
  • 如果当前Bean是多例对象,将当前Bean信息添加到正在创建多例缓存中,创建完毕以后移除
  • 如果当前Bean是其他类型,如Requtst,Session等类型,则自定义一个ObejctFacotry工厂,重写getObject方法,创建对象
  • 对象创建以后,判断当前对象是否为自己需要的对象,如果是直接返回;如果不是进行类型转换,如果类型转换失败,直接抛异常
接下来看一眼CreateBean的执行


推荐阅读