springboot系列文章之SpringApplication详解

本文详细分析了SpringApplication的初始化过程,包括推断应用类型、加载ApplicationContextInitializer和ApplicationListener、设置main方法所在类。接着,深入探讨了SpringApplication的run方法,涵盖Headless模式设置、加载SpringApplicationRunListeners、配置环境模块、创建ApplicationContext等关键步骤。通过本文,可以理解SpringBoot启动的完整流程。
摘要由CSDN通过智能技术生成

前言

还是从SpringBoot的启动类说起,这篇文章主要分析启动类中的SpringApplication

@SpringBootApplication
public class Application {


    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

可以看出main函数中重要的就是SpringApplication.run(),这可以分为两部分来探讨:
- SpringApplication的构造过程
- SpringApplication的run()方法

SpringApplication的初始化

首先进入SpringApplication的构造函数,先是单个参数的构造方法,后进入两个参数的构造方法,ResourceLoader是Spring的资源加载器,这里没有自定义的ResourceLoader传入,所以为NULL,而primarySources参数就是我们传入的Application.class启动类

public SpringApplication(Class<?>... primarySources) {
        this(null, primarySources);
    }
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        //1. 推断应用类型
        this.webApplicationType = deduceWebApplicationType();
        //2. initializer初始化模块,加载ApplicationContextInitializer
        setInitializers((Collection) getSpringFactoriesInstances(
                ApplicationContextInitializer.class));
        //3. 加载监听器
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        //4. 配置应用main方法所在的类
        this.mainApplicationClass = deduceMainApplicationClass();
    }

SpringApplication的初始化主要包括以下4个步骤:
- 推断应用类型
- 加载初始化构造器ApplicationContextInitializer
- 创建应用监听器
- 设置应用main()方法所在的类

1. 推断应用类型

this.webEnvironment=deduceWebApplicationType(); 判断应用的类型,是否是servlet应用还是reactive应用或者是none,webEnvironment中定义了这三种类型
webApplication
web

2. 加载初始化构造器ApplicationContextInitializer

setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class)): 通过SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer
init
进入loadFactoryNames方法,然后进入loadSpringFactories方法,获取当前ClassLoader下的所有META-INF/spring.factories文件的配置信息

而后通过loadSpringFactories(classloader).getOrDefault(factoryClassName,Collections.emptyList()) 从所有META-INF/spring.factories文件的配置信息的map中获取指定的factory的值
laod
spring
默认情况下,从 spring.factories 文件找出的 key 为 ApplicationContextInitializer 的类有如上图中所示4种

对于 ApplicationContextInitializer,它是应用程序初始化器,做一些初始化工作

public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
   

    /**
     * Initialize the given application context.
     * @param applicationContext the application to configure
     */
    void initialize(C applicationContext);

}

3. 创建应用监听器

setListeners()方法与setInitializers()方法类似,只不过它是使用SpringFactoriesLoader在应用的classpath的META-INT/spring.factories中查找并加载所有可用的ApplicationListener

        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

a
ApplicationListener,应用程序事件(ApplicationEvent)监听器:

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
   
    void onApplicationEvent(E event);
}

更详细的分析可以参阅我之前的文章: springboot系列文章之启动时初始化数据

4. 设置应用main()方法所在的类

在SpringApplication构造函数的最后一步,根据调用栈推断并设置main方法的定义类

    private Class<?> deduceMainApplicationClass() {
        try {
            StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
            for (StackTraceElement stackTraceElement : stackTrace) {
                if ("main".equals(stackTraceElement.getMethodName())) {
                    return Class.forName(stackTraceElement.getClassName());
                }
            }
        }
        catch (ClassNotFoundException ex) {
            // Swallow and continue
        }
        return 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值