Spring用了挺久的了,可是没系统作过总结,恰好前段时间在作一个Spring封装的项目,趁机回顾了下,便基于Spring framework 4.3.22作了源码分析。git
刚开始接触Spring时的入门例子大体以下:github
设置配置文件路径,初始化ApplicationContext而后获取Bean,处理完后关闭context便可。这一节先来了解Spring的启动过程。web
跟踪ClassPathXmlApplicationContext的构造方法能够看到以下内容:spring
里面设置了配置文件的路径,而且调用了父类AbstractApplicationContext的refresh方法,该方法完成了Spring环境的初始化。以下,为refresh方法的主要过程(为方便排版,去除了原来的注释和空格):segmentfault
下面将介绍各个方法步骤的内容,但不进行过多的深刻,后面会单独对每一个深刻的细节进行详细的介绍,这节先介绍大概过程。缓存
PrepareRefresh的内容如上,该方法主要进行环境的准备,包括Context的启动时间,活动状态,而后会设置context中的配置数据源,使用默认的StandardEnvironment对象,该对象添加了System.env()属性和System.properties()属性。initPropertySources方法用于初始化context 中 environment的属性源。在AbstractApplicationContext中为空实现。其余子类的实现以下:服务器
对于GenericWebApplicationContext和AbstractRefreshableWebApplicationContext的实现大体一致,都是:session
经过在getEnvironment方法中,重写createEnvironment方法,将默认的StandardEnvironment替换为StandardServletEnvironment, Environment的关系图为:app
于是会执行该类的initPropertySources方法,为context添加ServletContext和ServletConfig对应的配置属性源。具体的Environment中配置属性源的加载会在后面单独进行介绍。编辑器
该方法的实现以下,经过refreshBeanFacotry重置AbstractApplicationContext持有的BeanFacotry,而后经过getBeanFacotry得到该对象再返回。
AbstractApplicationContext中refreshBeanFacoty方法和getBeanFactory方法都是抽象方法,具体实如今AbstractRefreshableApplicationContext上。
如上,增长了方法的注释,重点在于loadBeanDefinitions方法,该抽象方法在具体实现子类上用于处理不一样场景下Bean定义的加载,如Xml配置,注解配置,Web环境等,具体实现会在后面展开。
目前,只是完成了Bean定义的加载,没有出现Bean的实例化。
为第2步返回的BeanFactory设置基础属性。包括:
具体能够看源码,这步主要预先设置公共的单例Bean并添加一些公共的后置处理动做,主要体如今BeanPostProcessor上。
全部Bean的定义已经加载完成,可是没有实例化,这一步能够修改bean定义或者增长自定义的bean,AbstractApplicationContext中为空实现。
如上,以AbstractRefreshableWebApplicationContext为例,其增长了ServletContextAwareProcessor后置处理器,用于处理ServletContextAware接口和ServletConfigAware接口中相关对象的自动注入。同时新增了Web相关的应用范围,包括:request,session,globalSession和application,并增长了各范围默认的单例对象。最后增长了Web环境相关的环境配置Bean,包括servletContext,servletConfig,contextParameters和contextAttributes。
该步骤的功能同第3步相似,都可以增长一些后置处理器。
在Spring容器中找出实现了BeanFactoryPostProcessor接口的Bean并执行。Spring容器会委托给PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法执行,内容以下:
invokeBeanFactoryPostProcessors在处理时,将BeanFactoryPostProcessor分为了两类进行处理,BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,其中BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor。执行的时候,先找出全部的BeanDefinitionRegistryPostProcessor执行再找出全部BeanFactoryPostProcessor执行。由于BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,因此执行后者时会过滤掉前者的内容。
在执行BeanDefinitionRegistryPostProcessor时,会按照以下的优先级,分类先执行postProcessBeanDefinitionRegistry方法,再统一执行全部的postProcessBeanFactory方法,,规则为:
在执行BeanFactoryPostProcessor也会按照如上的规则,执行BeanFactoryPostProcessor方法。
这里会实例化并初始化实现BeanFactoryPostProcessor接口的类并执行,若存在依赖的的Bean也会被初始化和实例化,具体的过程会在介绍Bean初始化过程时说明。
从Spring容器中找出的BeanPostProcessor接口的Bean,并添加到BeanFactory内部维护的List属性中,以便后续Bean被实例化的时候调用这个BeanPostProcessor进行回调处理。该方法委托给了PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法执行。执行过程同步骤5相似,也是按照优先级进行了筛选,具体顺序为:
其中MergedBeanDefinitionPostProcessor接口继承自BeanPostProcessor接口,于是,上述第(4)点的列表同头三点的列表是存在交集的。可是,AbstraceApplicationContext在添加BeanPostProcessor时,会先将存在的对象删除,再添加新的,以下:
于是执行顺序为于是执行顺序为:PriorityOrdered、Ordered、NotOrdered、MergedBeanDefinitionPostProcessor。
这里会实例化并初始化实现BeanPostProcessor接口的类,但不执行,若存在依赖的的Bean也会被初始化和实例化。
在Spring容器中初始化一些国际化相关的属性
在Spring容器中初始化事件广播器对象SimpleApplicationEventMulticaster,并将该对象做为单例applicationEventMulticaster注册到Context中。该广播器用于广播ApplicationEvent事件对应的ApplicationListener接口Bean。
PS:根据以上的顺序,在这以前实例化的Bean,都不会通过BeanFactoryPostProcessor和BeanPostProcessor的处理,包括由于依赖而实例化的Bean,还有提早经过new注册的Bean(只有直接调用BeanFactory.getBean方法获取的bean才会进行后置回调)。这里须要注意,Context提早将两种后置处理器的全部实现都提早加载了,因为实例化前须要将依赖的Bean提早实例化,因此被这两种后置处理器依赖的Bean的初始化动做,是不会被其监听到的。
模板方法,可用于refresh动做的扩展,默认为空实现。在SpringBoot中主要用于启动内嵌的web服务器。
找出系统中的ApplicationListener对象,注册到时间广播器中。若是有须要提早进行广播的时间,则执行广播.
实例化BeanFactory中已经被注册可是未实例化的全部实例(懒加载的不须要实例化),主要操做是BeanFacotry的preInstantiateSingletons方法。该方法分为两部分:
刷新后的其余动做,包括:
销毁全部已经注册的单例,对于实现了DisposableBean的类,会先单独进行销毁,以便执行回调方法,再清理全部单例的缓存信息和剩余的单例实例
将当前的活动状态标识为false
清除缓存
AbstractApplicationContext的close方法以下:
主要是调用doClose方法,而后判断是否有shutdownHook,若是有则移除该钩子,避免重复关闭,由于默认的shutdownHook也是调用的doClose方法。
doClose方法以下:
过程为:
这两个方法来自Lifecycle接口,以下,简单的调用了DefaultLifecycleProcessor的start和stop方法,回调Lifecycle的实现类。
咱们知道Spring中存在不少预设的接口,用于扩展。经过以上分析,目前获得的回调接口顺序以下:
后续对其余细节进行展开时,会看到更多的扩展接口,到时再更新上面的图。
我的公众号:啊驼