Spring Boot 启动流程

spring boot 启动流程必须懂。

启动类示例:

1
2
3
4
5
6
7
8
@SpringBootApplication
public class HiApplication {

    public static void main(String[] args) {
        // 先执行 SpringApplication 的构造方法,然后执行 run 方法
        SpringApplication.run(HiApplication.class, args);
    }
}

SpringApplication#run

源码位置: org.springframework.boot.SpringApplication#SpringApplication

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// SpringApplication 的构造方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    ... 
    // 决定 web 类型,如 servlet, reactive
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 加载 BootstrapRegistryInitializer 扩展
    this.bootstrapRegistryInitializers = new ArrayList<>(
            getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
    // 加载 ApplicationContextInitializer 扩展
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 加载 ApplicationListener 扩展,这个很重要
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

源码位置: org.springframework.boot.SpringApplication#run

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public ConfigurableApplicationContext run(String... args) {
    long startTime = System.nanoTime();
    // 会执行 BootstrapRegistryInitializer#initialize 方法
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;
    configureHeadlessProperty();
    // 加载 SpringApplicationRunListener 扩展
    SpringApplicationRunListeners listeners = getRunListeners(args);
    // 执行 SpringApplicationRunListener#starting 方法
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 准备 environment, 后面继续解析
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        configureIgnoreBeanInfo(environment);
        // 打印 banner
        Banner printedBanner = printBanner(environment);
        // 创建 applicationContext, 后面继续解析
        context = createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        // 准备 context, 后面继续解析
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        // 刷新 context, 后面继续解析
        refreshContext(context);
        // 空实现 
        afterRefresh(context, applicationArguments);
        ...
        // 执行 SpringApplicationRunListener#started 方法
        listeners.started(context, timeTakenToStartup);
        // 执行 ApplicationRunner 和 CommandLineRunner 
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        // 执行 SpringApplicationRunListener#failed 方法
        handleRunFailure(context, ex, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
        // 执行 SpringApplicationRunListener#ready 方法
        listeners.ready(context, timeTakenToReady);
    }
    catch (Throwable ex) {
        // 执行 SpringApplicationRunListener#failed 方法
        handleRunFailure(context, ex, null);
        throw new IllegalStateException(ex);
    }
    return context;
}

prepareEnvironment 准备环境

源码位置: org.springframework.boot.SpringApplication#prepareEnvironment

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
        DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
    // 根据 webType 来创建环境
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    // 环境中添加默认配置和命令行配置
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    // 没干啥事, 不重要
    ConfigurationPropertySources.attach(environment);
    // 执行 SpringApplicationRunListener#environmentPrepared 方法
    listeners.environmentPrepared(bootstrapContext, environment);
    // 默认配置移到最后
    DefaultPropertiesPropertySource.moveToEnd(environment);
    Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
            "Environment prefix cannot be set via properties.");
    // 绑定 spring.main 的属性到 SpringApplication
    bindToSpringApplication(environment);
    if (!this.isCustomEnvironment) {
        environment = convertEnvironment(environment);
    }
    // 没干啥事, 不重要
    ConfigurationPropertySources.attach(environment);
    return environment;
}

createApplicationContext 创建上下文

源码位置: org.springframework.boot.SpringApplication#createApplicationContext

1
2
3
4
protected ConfigurableApplicationContext createApplicationContext() {
    // 根据 webType 来创建 applicationContext
    return this.applicationContextFactory.create(this.webApplicationType);
}

源码位置: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.Factory#create

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 根据 webType 来创建 applicationContext
@Override
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
    return (webApplicationType != WebApplicationType.SERVLET) ? null
            : new AnnotationConfigServletWebServerApplicationContext();
}

// 构造函数
public AnnotationConfigServletWebServerApplicationContext() {
    // 非常重要,构造方法中注册了 ConfigurationClassPostProcessor,AutowiredAnnotationBeanPostProcessor
    this.reader = new AnnotatedBeanDefinitionReader(this);
    // 非常重要,扫描方法 ClassPathBeanDefinitionScanner#scan
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

prepareContext 准备上下文

源码位置: org.springframework.boot.SpringApplication#prepareContext

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
        ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments, Banner printedBanner) {
    // 设置环境
    context.setEnvironment(environment);
    // 设置 beanNameGenerator,resourceLoader,conversionService
    postProcessApplicationContext(context);
    // 执行 ApplicationContextInitializer#initialize
    applyInitializers(context);
    // 执行 SpringApplicationRunListener#contextPrepared 方法
    listeners.contextPrepared(context);
    // 发布 BootstrapContextClosedEvent 事件,不重要
    bootstrapContext.close(context);
    ...
    // lazy 初始化 bean
    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    // 不重要
    context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
    // Load the sources
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    // 加载启动类, 这样启动类就会作为一个 bean, 会被 ConfigurationClassPostProcessor 处理
    load(context, sources.toArray(new Object[0]));
    // 执行 SpringApplicationRunListener#contextLoaded 方法
    listeners.contextLoaded(context);
}

refreshContext 刷新上下文

源码位置: org.springframework.boot.SpringApplication#refreshContext

1
2
3
4
5
6
7
8
private void refreshContext(ConfigurableApplicationContext context) {
    // 注册 shutdown 钩子
    if (this.registerShutdownHook) {
        shutdownHook.registerApplicationContext(context);
    }
    // 刷新, 实现类为 ServletWebServerApplicationContext
    refresh(context);
}

源码位置: org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#refresh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Override
public final void refresh() throws BeansException, IllegalStateException {
    try {
        // 父类为 AbstractApplicationContext
        super.refresh();
    }
    catch (RuntimeException ex) {
        WebServer webServer = this.webServer;
        if (webServer != null) {
            webServer.stop();
        }
        throw ex;
    }
}

源码位置: org.springframework.context.support.AbstractApplicationContext#refresh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        ...
        // 初始化 ServletPropertySources 
        prepareRefresh();
        // 做一些准备操作,如忽略依赖接口,注册可解析的依赖, 注册默认的Bean
        prepareBeanFactory(beanFactory);
        try {
            // 子类实现为 AnnotationConfigServletWebServerApplicationContext
            // 读取和扫描 beanDefinition(spring boot 没有用)
            postProcessBeanFactory(beanFactory);

            // 执行 BeanFactoryPostProcessor (按照 PriorityOrdered,Ordered,nonOrdered),不解析
            // 里面会用到 ConfigurationClassPostProcessor 扫描启动类
            invokeBeanFactoryPostProcessors(beanFactory);

            // 注册 BeanPostProcessor (按照 PriorityOrdered,Ordered,nonOrdered),不解析
            registerBeanPostProcessors(beanFactory);

            // 注册 MessageSource(国际化)不用关心
            initMessageSource();

            // 注册 ApplicationEventMulticaster
            initApplicationEventMulticaster();

            // 子类实现为 AnnotationConfigServletWebServerApplicationContext
            // 创建了 servlet 容器
            onRefresh();

            // 注册 ApplicationListener
            registerListeners();

            // 初始化 beanFactory, 初始化 non-lazy-init bean, 非常重要,会在【bean 初始化】章节解析
            finishBeanFactoryInitialization(beanFactory);

            // 执行 LifecycleProcessor#onRefresh 方法,发布 ContextRefreshedEvent 事件
            finishRefresh();
        }
        catch (BeansException ex) {
            ...
        } finally {
            ...
        }
    }
}
0%