#.前言
不得不说我们的SpringBoot给Java开发人员带来了很多的便利之处。比如:不用再配置一些的xml文件了;加载程序的容器也帮我们嵌套在代码里了;Web的中心控制器入口也自动写在了代码里;真正的做到了随处可见的自启动及兼容性。既然说是随处可见的自启动那是怎么自启动的呢?那我们一起来看看吧。
#.启动入口之SpringApplication.run
一.实例化构造器SpringApplication
- 加载属性,如:资源加载器ResourceLoader
- 设置web项目加载的类型WebApplicationType(一般为SERVLET)
- 读取配置文件META-INF/spring.factories,从配置文件中加载实例化上下文的初始化加载器ApplicationContextInitializer和应用监听器ApplicationListener
- 设置属性主要的应用程序加载类:mainApplicationClass:Class<?>
二.执行run()函数
- 使用StopWatch来记录程序启动过程的时间
- 筛选监听器SpringApplicationRunListener,并实例化其实现类EventPublishingRunListener,主要用于实例化处理事件与监听器对应关系ˆ的广播站SimpleApplicationEventMulticaster
- 解析出之前获取到的监听器的事件为ApplicationStartingEvent,监听器类型为EventPublishingRunListener,共4个并启动
- 获取调用run方法传递的参数或者命令行传递的一些配置参数,如:启动debug模式的环境配置(-ea)、配置文件的前缀名称(spring.config.name)
- 准备运行项目的环境配置(StandardServletEnvironment),如:格式转换器ConfigurablePropertyResolver、环境变量配置ConfigurablePropertyResolver(系统环境变量的配置systemProperties、项目的配置文件applicationConfig)
- 从系统变量中获取名称为spring.beaninfo.ignore的需要忽略加载的Bean
- 打印一些Banner数据
- 使用反射创建项目的上下文环境,一般情况下我们是使用Servlet类型的上下文类AnnotationConfigServletWebServerApplicationContext
1).创建默认的资源加载器DefaultResourceLoader
2).创建抽象化的应用上下文,如:读取环境变量的配置文件DefaultResourceLoader和资源解析器PathMatchingResourcePatternResolver、及实例化BeanFacotry并控制其创建的生命周期、国际化的消息的解析
3).通过资源加载器获取配置文件及通过BeanFactory去注册Bean并设置bean属性、设置上下文中需要忽略加载的bean
4).获取一些通用的WEB程序的上下文环境,重写了一些bean的后置处理器及加载环境变量的类
5).实例化ServletWebServerApplicationContext的上下文环境,如:创建WebServer
6).扫描加载一些通过注解加载的类及类路径下面的Bean,如:@Configuration、@Component,和使用了@Conditional的条件评估容器ConditionEvaluator - 异常日志报表的加载及打印
- 上下文环境的准备
1).设置上下文中的环境变量
2).Application上下文中的一些后置处理,如:将格式转换器服务ConvertService
3).执行了SpringApplication初始化加载器的7个实现类的初始化方法initialize(),并给context初始化了2个BeanFacotry的后置处理器、3个项目监听器ApplicationListener(socket的端口信息的初始化加载器、服务器端口信息的初始化加载器、配置的一些warning日志打印的初始化加载器),及注册了2个单例类(自动打印配置的表、上下文的应用Id的上下文的初始化加载器) - 上下文环境的刷新
1).复制并刷新contenxt中的listener
2).获取并刷新BeanFacotry及设置其上下文的序列化Id
3).准备一些BeanFactory的数据配置,如:类加载器、Bean的表达解析器StandardBeanExpressionResolver、后置处理器、依赖解析器、需要忽略的接口
4).设置bean工厂的后置处理器,如:上下文中的Aware的处理器、应用监听器的检测、web容器的上下文的Aware处理器(设置了Web程序上下文的作用域、及Web作用域的依赖解析器)
5).执行AbstractApplicationContext上下文的BeanFactory的后置处理器
* a.执行bean工厂中类型为BeanDefinitionRegistry及其实现类的后置处理器,按照PriorityOrdered、Ordered及无序的优先级执行*
* 注:ConfigurationClassPostProcessor比较关键:会去识别从配置文件配置的Bean并标注了可以自动实例化Bean的注解去执行符合通过@Conditional筛选出的执行器,如:Servelt的
DispatcherServletAutoConfiguration*
* b.执行上下文及它的BeanFactory的工厂后置器(BeanFactoryPostProcessors),同样按照PriorityOrdered、Ordered及无序的优先级执行*
6).注册上下文及它的BeanFactory中管理的Bean的后置处理器
7).初始化一些上下文的信息源,如:国际化信息的处理
8).初始化一些应用项目事件的通道处理器(主要用于处理事件与监听器及其对应关系)
9).刷新一些特殊的上下文子类中的特殊化的Bean,如:去创建WebServer容器的Bean
10).核对一些监听器并注册这些监听器
11).完成BeanFactory的初始化加载,并保留非懒加载的单列bean
12).contenxt刷新后的操作
a.清理资源缓存,初始化上下文的生命周期处理器并刷新它,发布ContextRefreshedEvent的事件;
b.在Web的上下文中去启动WebServer容器
13).在finally中重置清理一些公共的缓存 - 完成上下文的刷新(在现有版本中并没做操作)
- 使用StopWatch去记录程序完成启动的时间,并在日志中以Info的格式打印出来
- 执行启动了但没有调用的监听器,即在上下文中需要懒加载的监听器
- 执行调用ApplicationRunner、CommandLineRunner类别的runner()方法
- 执行发布事件为ApplicationReadyEvent类的监听器
#.总结
其实上面说了这么多,我们的程序启动无外乎几点:环境、资源、容器、启动时间、管理器、日志记录、异常处理,而在SpringBoot中自动加载关键是要有监听器去识别我们的注解,而这个过程又分为准备、启动中、刷新、启动完成、发布已准备好的监听