Spring容器启动流程
一些Spring相关概念
- Spring是一个IoC容器 Spring被称为一个IoC容器,因为它可以管理对象之间的依赖关系。在使用Spring之前,我们需要在代码中手动设置对象之间的依赖关系。但是在使用Spring之后,Spring会负责管理这种依赖关系,当我们需要使用对象时,只需要从Spring中获取即可。
- BeanDefinition Spring中的Bean与普通Java类的实例有所不同。Spring中的Bean除了表示某个类的对象或实例外,还增加了许多属性,例如作用域、是否延迟初始化、是否单例等。为了描述Spring中Bean的这些额外属性,Spring引入了BeanDefinition类。
- BeanDefinitionReader Spring支持多种方式进行Bean的配置,例如XML、properties、groovy、注解等。BeanDefinitionReader是Spring用来读取这些Bean配置的类,它将配置转化为BeanDefinition。
- BeanDefinitionRegistry 在BeanDefinitionReader将配置解析为BeanDefinition之后,需要将这些BeanDefinition保存到BeanDefinitionRegistry中。BeanDefinitionRegistry就像一个仓库,保存着原材料(即BeanDefinition),供之后的生产使用。
- BeanFactory BeanFactory是Spring用来生产Bean的工厂。BeanFactory会根据BeanDefinition将Bean生成,并保存下来。
- DefaultListableBeanFactory DefaultListableBeanFactory是BeanFactory的实现类,它实现了BeanDefinitionRegistry和BeanFactory接口,因此可以保存Bean定义,并根据定义生成Bean。
- BeanPostProcessor BeanPostProcessor是Spring中用来干预Bean生产过程的接口。通过实现BeanPostProcessor,我们可以在Bean初始化前后进行自定义的处理。例如,AOP就是利用BeanPostProcessor来实现的。
- BeanFactoryPostProcessor BeanFactoryPostProcessor是Spring中用来干预BeanFactory的接口。通过实现BeanFactoryPostProcessor,我们可以对BeanFactory进行定制化。例如,我们可以将所有Bean的作用域都改成原型(默认是单例)。
- ParentBeanFactory 在Spring中,可能存在多个BeanFactory。这些BeanFactory之间可能存在“父工厂”和“子工厂”的关系。父工厂中定义的Bean可以被子工厂继承和使用。
- Spring中的缓存 Spring中提供了多个缓存,用于提高Bean的创建效率和性能。其中包括mergedBeanDefinitions缓存、beanDefinitionMap缓存、singletonObjects缓存、earlySingletonObjects缓存、singletonFactories缓存和singletonsCurrentlyInCreation缓存等。
启动流程
- 初始化Spring容器,注册内置的BeanPostProcessor的BeanDefinition到容器中
- 将配置类的BeanDefinition注册到容器中
- 调用refresh()方法刷新容器
this() 初始化 Spring 容器
spring容器的初始化时,通过this()调用了无参构造函数,主要做了以下三个事情:
(1)实例化BeanFactory【DefaultListableBeanFactory】工厂,用于生成Bean对象
(2)实例化BeanDefinitionReader注解配置读取器,用于对特定注解(如@Service、@Repository)的类进行读取转化成 BeanDefinition 对象,(BeanDefinition 是 Spring 中极其重要的一个概念,它存储了 bean 对象的所有特征信息,如是否单例,是否懒加载,factoryBeanName 等)
(3)实例化ClassPathBeanDefinitionScanner路径扫描器,用于对指定的包目录进行扫描查找 bean 对象
register() 注册 Config 类到 Spring 中
这个步骤主要是用来解析用户传入的 Spring 配置类,解析成一个 BeanDefinition 然后注册到容器中。
refresh() 容器刷新
refresh()主要用于容器的刷新,Spring 中的每一个容器都会调用 refresh() 方法进行刷新,无论是 Spring 的父子容器,还是 Spring Cloud Feign 中的 feign 隔离容器,每一个容器都会调用这个方法完成初始化。refresh()可划分为12个步骤。
① prepareRefresh()刷新前的预处理:
② obtainFreshBeanFactory():获取在容器初始化时创建的BeanFactory:
③ prepareBeanFactory(beanFactory):BeanFactory的预处理工作,向容器中添加一些组件:
④ postProcessBeanFactory(beanFactory):子类重写该方法,可以实现在BeanFactory创建并预处理完成以后做进一步的设置
⑤ invokeBeanFactoryPostProcessors(beanFactory):在BeanFactory标准初始化之后执行BeanFactoryPostProcessor的方法,即BeanFactory的后置处理器:
⑥ registerBeanPostProcessors(beanFactory):向容器中注册Bean的后置处理器BeanPostProcessor,它的主要作用是干预Spring初始化bean的流程,从而完成代理、自动注入、循环依赖等功能
⑦ initMessageSource():初始化MessageSource组件,主要用于做国际化功能,消息绑定与消息解析:
⑧ initApplicationEventMulticaster():初始化事件派发器,在注册监听器时会用到:
⑨ onRefresh():留给子容器、子类重写这个方法,在容器刷新的时候可以自定义逻辑
⑩ registerListeners():注册监听器:将容器中所有的ApplicationListener注册到事件派发器中,并派发之前步骤产生的事件:
⑪ finishBeanFactoryInitialization(beanFactory):初始化所有剩下的单实例bean,核心方法是preInstantiateSingletons(),会调用getBean()方法创建对象;
⑫ finishRefresh():发布BeanFactory容器刷新完成事件。