一、Spring Boot启动jar包原理
ioc容器带动了内嵌tomcat的启动
1、SpringApplication初始化阶段
1)编写Spring Boot启动类
@SpringBootApplication
public class CyanSpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(CyanSpringbootApplication.class, args);
}
}
2)SpringApplication初始化是通过调用其静态方法run(Class<?> primarySource, String... args)来启动应用
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
3)如果稍微留心观察,SpringApplication对象构造过程就在其中
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
4)SpringApplication构造过程
public SpringApplication(Class<?>... primarySources) {
this((ResourceLoader)null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// ...
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 保存主配置类primarySources
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
// 推断Web应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 加载Spring应用上下文初始化器
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 加载Spring应用事件监听器
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
// 推断应用引导类
this.mainApplicationClass = this.deduceMainApplicationClass();
}
至此,SpringApplication对象创建完成
2、SpringApplication运行阶段
1)传入args参数,调用SpringApplication对象的run()方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 创建一个容器对象
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
// 去classpath下的meta-info/spring.factories下获取SpringApplicationRunListener监听器(事件发布监听器)
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 准备环境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
// 打印Spring Boot图标
Banner printedBanner = this.printBanner(environment);
// 根据当前是否为Web环境来决定是创建Web容器还是普通的IOC容器
context = this.createApplicationContext();
// 去classpath下的meta-info/spring.factories下获取异常报告类SpringBootExceptionReporter
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
// 容器预准备流程
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
2)
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
// 获取或者创建一个环境
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
// 配置环境,把命令行参数配置到环境中去
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach((Environment)environment);
// 循环调用SpringApplicationRunListener.environmentPrepared()环境预准备方法
listeners.environmentPrepared((ConfigurableEnvironment)environment);
// 把环境对象绑定到SpringApplication对象上
this.bindToSpringApplication((ConfigurableEnvironment)environment);
if (!this.isCustomEnvironment) {
environment = (new EnvironmentConverter(this.getClassLoader())).convertEnvironmentIfNecessary((ConfigurableEnvironment)environment, this.deduceEnvironmentClass());
}
ConfigurationPropertySources.attach((Environment)environment);
return (ConfigurableEnvironment)environment;
}
二、Spring Boot启动war包原理
外置的tomcat带动了ioc容器的启动