作为Springboot最重要的组件,SpringApplication扮演着创建并启动ApplicationContext及其他组件的总指挥角色。SpringApplication是打开SpringBoot应用的钥匙,这一节我们简单的梳理以下SpringApplication
- SpringApplication类解析
SpringApplication的属性列表,上面有很多重要的属性,比如DEFAULT_***_CONTEXT_CLASS;
primarySources;sources;mainApplicationClass;environment;applicationContextClass;webApplicationType;initializers;listeners等,这些属性在接下来的启动过程中扮演着非常重要的角色,这里暂时不表
- SpringBoot的方法解析
上面的看到方法非常多,我们可以从主要的方法入手。比如SpringApplication启动方法org.springframework.boot.SpringApplication#run(java.lang.String...)
- SpringApplication 启动方法解析
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
...忽略掉不重要的
//获取spring.factories中配置的SpringApplicationRunListener
SpringApplicationRunListeners listeners = getRunListeners(args);
//广播ApplicationStartingEvent
listeners.starting();
try {
//获取输入的参数
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//准备Environment,并且广播ApplicationEnvironmentPreparedEvent
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
//忽略一部分bean
configureIgnoreBeanInfo(environment);
//标志旗
Banner printedBanner = printBanner(environment);
//获取适当的符合当前应用环境的ApplicationContext
context = createApplicationContext();
//异常报告
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//准备ApplicationContext,广播ApplicationContextInitializedEvent/ApplicationPreparedxEvent
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//刷新ApplicationContext。触发ApplicationContext生命周期
refreshContext(context);
//
afterRefresh(context, applicationArguments);
stopWatch.stop();
//广播ApplicationStartedEvent
listeners.started(context);
callRunners(context, applicationArguments);
}
//广播ApplicationReadyEvent事件
listeners.running(context);
return context;
}
上面的代码就是SpringApplication#run(String...args)的主要内容:
- 获取在jar包中配置的spring.factories文件配置的SpringApplicationRunListener,统一交给SpringApplicationRunListeners的结合类处理
- 拼装输入参数ApplicationArguments
- 新建一个合适的Envrionment,非web环境时是StandardEnvironment,Servelt时是StandardServletEnvironment,把输入的参数当作CommandLinePropertySource放在Environment中的第一位,获取SpringApplication中的激活Profile。广播ApplicationEnvironmentPreparedEvent;
- 在Environment或者是SystemProperties中配置忽略的bean
- 创建一个合适的ApplicationContext,用到的是上面讲到的DEFAULT_***_CONTEXT_CLASS;
- 准备applicationContext。把Envrionment赋值给ApplicationContext,设置一些特殊的bean,beanNameGenerator,resourceLoader,ConversionService,从jar包中的spring.factories文件中获取ApplicationContexInitializer,并初始化ApplicationContext,发布ApplicationContextInitializedEvent,获取BeanFactory。配置特殊的bean,加载SpringApplication配置的sources类。发布ApplicationPreparedEvent事件
- 调用ApplicationContext的refresh方法,启动ApplicationContext的生命周期
- 启动ApplicationRunner和CommandLineRunner
- 上下文中广播ApplicationStartedEvent
- 上下文中广播ApplicationReadyEvent
通过上面的SpringApplication的run方法解析,我们可以看到SpringApplication把ApplicationContext的Envrionment和BeanFactory的维护功能提前,并且包含了ApplicationContext的声明周期,这也是我们第二节讲到的Springboot青出于蓝的地方
我们看到SpringBoot对于Spring-framework的生命周期的扩展,让我们有更多的机会改变程序的运行轨迹。
下一节我们继续解析一下上面的第三步和第5步,怎么创建合适的Environment和合适的ApplicationContext