SpringBoot启动流程及自动配置(上)
1.1.1 SpringBoot启动总体流程
SpringBoot启动总体分为三个步骤:
l 第一部分进行SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器,
l 第二部分实现了应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块及核心的创建上下文环境模块
l 第三部分是自动化配置模块,该模块作为springboot自动配置核心
1.1.2 SpringBoot应用程序入口
每个SpringBoot程序都有一个主入口,也就是main方法,main里面调用SpringApplication.run()启动整个spring-boot程序,该方法所在类需要使用@SpringBootApplication注解,以及@ImportResource注解(if need),@SpringBootApplication包括三个注解,功能如下:
l @EnableAutoConfiguration:SpringBoot根据应用所声明的依赖来对Spring框架进行自动配置
l @SpringBootConfiguration(内部为@Configuration):被标注的类等于在spring的XML配置文件中(applicationContext.xml),装配所有bean事务,提供了一个spring的上下文环境
l @ComponentScan:组件扫描,可自动发现和装配Bean,默认扫描SpringApplication的run方法里的Booter.class所在的包路径下文件,所以最好将该启动类放到根包路径下
1.1.3 创建SpringApplication对象
1.1.4 启动SpringBoot应用
l 创建了应用的监听器SpringApplicationRunListeners并开始监听
l 创建SpringBoot配置环境ConfigurableEnvironment(如果是通过web容器发布,会加载StandardEnvironment,其最终也是继承了ConfigurableEnvironment);配置环境(Environment)加入到监听器对象中(SpringApplicationRunListeners);加载属性文件资源;
l 创建run方法的返回对象:ConfigurableApplicationContext(应用配置上下文),我们可以看一下创建方法:
方法会先获取显式设置的应用上下文(applicationContextClass),如果不存在,再加载默认的环境配置(通过是否是web environment判断),默认选择AnnotationConfigApplicationContext注解上下文(通过扫描所有注解类来加载bean),最后通过BeanUtils实例化上下文对象,并返回
l 回到run方法内,prepareContext方法将listeners、environment、applicationArguments、banner等重要组件与上下文对象关联
l 接下来的refreshContext(context)方法(调用基类: AbstractApplicationContext的初始化方法如下)将是实现spring-boot-starter-*(mybatis、redis等)自动化配置的关键,包括spring.factories的加载,bean的实例化等核心工作
1) prepareBeanFactory(beanFactory):设置beanFactory的classloader,BeanExpressionResolver,PropertyEditorRegistrar,ApplicationContextAwareProcessor和忽略xxxxAware,注册依赖,还有ApplicationListenerDetector
ApplicationContextAwareProcessor:只是将applicationContext传递给ApplicationContextAwareProcessor,方便后面的xxxAware调用
忽略xxxxAware:忽略这些Aware接口实现类中与接口set方法中入参类型相同的属性的的自动注入这样就保证了关键的类是由spring容器自己产生的而不是我们注入的,
自动注入不是指的@AutoWire 而是指的是beans的default-autowire="byType" 或在bean的autowire="byType" ,这样spring 回去ioc容器寻找类型相似的类型给其注入,如果实现了spring 的xxaware接口,就不会自动注入记载filterPropertyDescriptorsForDependencyCheck删除与入参类型相同的属性
注册依赖:即指定一些类自动注入的实例是spring指定的实例对象
ApplicationListenerDetector:检测实现了ApplicationListener的实现类,因为有些实现类,无法通过getBeanNamesForType获取到
2) postProcessBeanFactory(beanFactory):继续设置ignoreDependencyInterface(ServletContextAware)还有annotatedClasses,basePackages如果存在就设置
3) invokeBeanFactoryPostProcessors(beanFactory):从beanFactoryPostProcessors获取BeanFactoryPostProcessor,然后先执行BeanDefinitionRegistryPostProcessor类型的postProcessBeanDefinitionRegistry,继续从beanFactory获取BeanDefinitionRegistryPostProcessor类型的bean然后执行postProcessBeanDefinitionRegistry,执行的过程按照PriorityOrdered,Ordered,普通的类型进行执行,然后优先执行registryProcessors的postProcessBeanFactory在执行regularPostProcessors的postProcessBeanFactory,再从BeanFactory获取PriorityOrdered,Ordered,普通的类型三种类型的BeanFactoryPostProcessor,并按照顺序执行。
总结:从之前加入的beanFactoryPostProcessor先执行postProcessBeanDefinitionRegistry(假如是BeanDefinitionRegistryPostProcessor)然后在执行postProcessBeanFactory方法,然后从beanFactory获取BeanFactoryPostProcessor 然后执行postProcessBeanFactory,执行过程中都要按照PriorityOrdered,Ordered,普通的类型三种类型的顺序执行
4) registerBeanPostProcessors:从beanFactory获取BeanPostProcessor分别按照PriorityOrdered,Ordered,普通的类型注册BeanPostProcessor
5) BeanPostProcessor和BeanFactoryPostProcessor:前者是对bean初始化前后进行设置,后者可以对beanFactory进行修改 或者,可以对beanDefinition进行修改或者增加或者初始化渴望提前初始化的bean
6) initMessageSource():一般是我们用来初始化我们国际化文件的
7) initApplicationEventMulticaster():设置applicationEventMulticaster,spring发布各种事件就依靠他,这个和springboot发布事件使用相同的类
8) onRefresh():初始化其他的子容器类中的bean,同时创建spring的内置tomcat,这在后期Springboot内嵌式tomcat中详细阐述
9) registerListeners():添加用户设置applicationListeners,然后从beanFactory获取ApplicationListener,然后发布需要earlyApplicationEvents事件
10) finishBeanFactoryInitialization(beanFactory):实例化非懒加载的剩余bean
11) finishRefresh:清理资源缓存,初始化lifecycle,调用lifecycle的onrefresh,发布ContextRefreshedEvent的事件,激活JMX,启动tomcat
配置结束后,Springboot做了一些基本的收尾工作,返回了应用环境上下文。回顾整体流程,Springboot的启动,主要创建了配置环境(environment)、事件监听(listeners)、应用上下文(applicationContext),并基于以上条件,在容器中开始实例化我们需要的Bean,至此,通过SpringBoot启动的程序已经构造完成。