一、启动过程
(一)、new SpringApplication
1、判断是否为web环境
2、从spring.factories中加载: key = ApplicationContextInitializer
注:改接口是执行refresh()方法之前调用
3、从spring.factories中加载: key = ApplicationListener
4、从当前的线程中的栈帧中找到main() 方法所在的类
(二)、run()方法
1、设置系统变量 java.awt.headless = true
2、从spring.factories 中加载 SpringApplicationRunListener
注:SpringApplicationRunListener 会伴随着springApplication的整个生命周期
3、利用args实例化ApplicationArguments
4、根据配置文件、JVM启动参数实例化并配置ConfigurableEnvironment
5、实例化 ConfigurableApplicationContext
6、准备 ConfigurableApplicationContext
a、设置ConfigurableEnvironment
b、注册bean:BeanNameGenerator
c、执行所有的 ApplicationContextInitializer
d、注册bean:ApplicationArguments
e、注册bean:PrintedBanner
f、加载所有的资源(sources)到ConfigurableApplicationContext 中
7、执行context中的refrest()方法
注: refreshContext()--->refresh()--->AbstractApplicationContext.class refresh()--->finishBeanFactoryInitialization() 执行非懒加载的bean--->ConfigurableListableBeanFactory.class preInstantiateSingletons()
实例化非懒加载的bean时,构造方法和后处理bean的前方法一起执行
8、执行ApplicationRunner、CommandlineRunner 接口中的方法
注:两个接口中的方法是在容器启动成功后的最后一步调用
(三)、关键组件加载顺序
1、AService static===main
2、AService 构造方法===main
3、setter ===main
4、BeanPostProcessor-before 接口 ===main
5、@PostConstruct===main
a、执行初始化代码,如开启资源、读取配置文件等。
6、InitializingBean 接口 ===main
a、依赖于 Spring 容器的某些功能,或者需要确保所有的 Spring 特定生命周期事件已经完成,那么实现 InitializingBean 接口可能更合适。
7、BeanPostProcessor-after 接口 ===main
8、ationListener<ContextRefreshedEvent> 接口 ===main 初始化缓存数据,服务自检
9、CommandLineRunner 接口 ===main
a、微服务注册
package com.study.testInit;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
/**
* @author sunxuejian
* @date: 2024/1/28
* @time: 3:54 PM
* Description:
*/
@Service
public class AService implements InitializingBean, ApplicationListener<ContextRefreshedEvent>, CommandLineRunner {
static {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("---> AService static===" + Thread.currentThread().getName());
}
private BService bService;
public AService() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("---> AService 构造方法===" + Thread.currentThread().getName());
}
@Resource
public void setBService(BService bService) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
this.bService = bService;
System.out.println("---> setter ===" + Thread.currentThread().getName());
}
@PostConstruct
public void init() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("---> @PostConstruct===" + Thread.currentThread().getName());
}
@Override
public void afterPropertiesSet() throws Exception {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
this.bService = bService;
System.out.println("---> InitializingBean 接口 ===" + Thread.currentThread().getName());
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
this.bService = bService;
System.out.println("---> ApplicationListener 接口 ===" + Thread.currentThread().getName());
}
@Override
public void run(String... args) throws Exception {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
this.bService = bService;
System.out.println("---> CommandLineRunner 接口 ===" + Thread.currentThread().getName());
}
}