spring boot 启动解析

使用debug模式去运行程序,阅读源码

 初始化流程

spring 容器的初始化

  1. 创建了SpringApplication对象实例,实例中通过path去判段使用的web容器的类型,并且调用了对象实例的run方法

  2. run方法中启动了计时器,创建并启动所有监听器,初始化运行环境(加载配置),

  3. 判断应该创建哪一种ApplicationContext,创建后和环境绑定

  4. 通过SpringFactoris-Loader加载classpath中的所有spring-Initializer,对context在refresh做处理,通知监听器Context准备好了

  5. 将@EnableAutoConfiguration获取的所有配置一起其他IOC容器配置加载到ApplicationContext

 

Spring boot程序入口,最后调用了run方法 

@SpringBootApplication
public class LearnApplication {

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

    }

}

调用静态的run方法之后,去新建一个SpringApplication对象

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        return (new SpringApplication(primarySources)).run(args);
    }

 SpringApplication的构造方法

public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();//判断web应用的类型
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

webApplication的判断逻辑

    static WebApplicationType deduceFromClasspath() {
        if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
            return REACTIVE;
        } else {
            String[] var0 = SERVLET_INDICATOR_CLASSES;
            int var1 = var0.length;

            for(int var2 = 0; var2 < var1; ++var2) {
                String className = var0[var2];
                if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
                    return NONE;
                }
            }

            return SERVLET;
        }
    }

回到具体调用的run方法

 public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();//启动计时器
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();//设置headless模式,该模式一般用于服务端没有显示器、键盘、鼠标等设备的情况
        SpringApplicationRunListeners listeners = this.getRunListeners(args);//创建listeners
        listeners.starting();//启动所有的监听器

        Collection exceptionReporters;
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);//初始化环境,包括加载配置文件、profiles
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);//Banner可以定义springboot启动输出的图形
            context = this.createApplicationContext();//根据new SpringBootApplication构造函数中web容器类型去初始化容器
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);//过SpringFactoris-Loader加载classpath中的所有spring-Initializer
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);//配置springboot将要使用的环境,在容器初始化之前调用initializer
            this.refreshContext(context);//判断是否注册ShutdownHoo,该方法后IOC容器可用
            this.afterRefresh(context, applicationArguments);//通过SpringFactoris-Loader加载classpath中的所有spring-Initializer,对context做处理
            stopWatch.stop();//Application创建好计时器结束
            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);
        }
    }

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值