一、找到启动类
1.java -jar xxx.jar
java会找到MANIFEST.MF文件的Main-Class,启动springboot JarLauncher的main方法
Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Implementation-Title: demo
Implementation-Version: 0.0.1-SNAPSHOT
Start-Class: com.example.demo.DemoApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.3.11.RELEASE
Created-By: Maven Jar Plugin 3.2.0
Main-Class: org.springframework.boot.loader.JarLauncher
2.JarLauncher.launch方法大致过程
1)获取到BOOT-INF下面的classes文件与lib包下面的jar
2)创建LaunchedURLClassLoader,放入线程上下文,用于加载jar(可以加载jar中jar)
3.获取到Start-Class启动类,利用反射,调用main方法,这样就能到达我们使用的main方法了。
二、Main方法启动
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(DemoApplication.class);
// springApplication.setApplicationContextFactory((webApplicationType) -> new CustomApplicationContext());
springApplication.run(args);
}
1.初始化SpringApplication
1). 获取启动类
2).获取web应用类型
3).读取了对外扩展的ApplicationContextInitializer ,ApplicationListener
4).根据main推算出所在的类
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));
// 根据classpath 下的类,推算当前web应用类型(webFlux, servlet)
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 就是去spring.factories 中去获取所有key:org.springframework.context.ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//就是去spring.factories 中去获取所有key: org.springframework.context.ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 根据main方法推算出mainApplicationClass
this.mainApplicationClass = deduceMainApplicationClass();
}
2.启动
2.1)启动事件
- SpringApplicationRun 开始的start事件
- environmentPrepared 环境准备事件 ConfigFileApplicationListener(先加载properties,后加载yml)
- contextPrepared 上下文准备事件
- contextLoaded 上下文加载事件
- started完后事件(执行完refresh方法)
- running执行中事件
2.2 步骤
1).启动事件,通知我要启动了
listeners.starting();
2).获取环境运行的参数,通过environmentPrepared会初始化properties和yml文件。
3).根据容器类型获取applicationcontext,SERVLET获取AnnotationConfigServletWebServerApplicationContext
4).填充applicationcontext,并发布上下文已准备事件(contextPrepared),加载主类配置,发布contextLoaded事件
5).执行applicationcontext.refresh方法,并启动内置tomcat。
6).发布started和running事件