springboot的启动源码流程(菜鸟笔记)

springboot的启动源码流程

1.几个重要的事件回调机制

//放在类路劲下的META-INF/spring.factories文件中
ApplicationContextInitializer
ApplicationListener

//先执行ApplicationRunner,再执行CommandLineRunner
ApplicationRunner
CommandLineRunner

2.springboot.run(Main.class)分为两部分

//首先spring容器的创建
//执行容器的run方法
new SpringApplication(primarySources).run(args);

3.spring容器的创建

	
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    //保存主配置类
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    //判断是否是web应用
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    
    //从类路劲下找到\META-INF\spring.factories配置所有的ApplicationContextInitializer然后保存起来
    //getSpringFactoriesInstances
    //1.从META-INF/spring.factories文件中找实现了ApplicationContextInitializer接口的所有类
    	//1.1 实现类如下
        org.springframework.context.ApplicationContextInitializer=\
        org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
        org.springframework.boot.context.ContextIdApplicationContextInitializer,\
        org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
        org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
    //2.createSpringFactoriesInstances 获取到的全类名,通过反射创建实例
	//3.保存ApplicationContextInitializer创建的实例
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    
    
    //从类路劲下找到\META-INF\spring.factories配置所有实现了ApplicationListener接口的类
    //getSpringFactoriesInstances
    //1.从META-INF/spring.factories文件中找实现了ApplicationListener接口的所有类
    //1.1 实现类如下:
    	org.springframework.context.ApplicationListener=\
        org.springframework.boot.ClearCachesApplicationListener,\
        org.springframework.boot.builder.ParentContextCloserApplicationListener,\
        org.springframework.boot.context.FileEncodingApplicationListener,\
        org.springframework.boot.context.config.AnsiOutputApplicationListener,\
        org.springframework.boot.context.config.ConfigFileApplicationListener,\
        org.springframework.boot.context.config.DelegatingApplicationListener,\
        org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
        org.springframework.boot.context.logging.LoggingApplicationListener,\
        org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
    //2.createSpringFactoriesInstances 获取到的全类名,通过反射创建实例
	//3.保存ApplicationListener创建的实例
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //从配置类中找到有main方法的主类
    this.mainApplicationClass = deduceMainApplicationClass();
}

在这里插入图片描述

在这里插入图片描述

4.执行容器的run方法

/**
* Run the Spring application, creating and refreshing a new ApplicationContext
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
    //用来打印,方法执行的时间,
    //如:Started BootMasterApplication in 56.783 seconds (JVM running for 69.93)
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    //1.申明ioc容器
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    //2.配置环境变量  java.awt.headless='true'
    configureHeadlessProperty();
    
    //3.在\META-INF\spring.factories中找实现类接口SpringApplicationRunListener的所有类,并依次创建类的实例
    SpringApplicationRunListeners listeners = getRunListeners(args);
    //4.回调SpringApplicationRunListener.starting();依次开启所有的监听器
    listeners.starting();
    try {
        //5.包装传入参数  在Idea工具中添加命令行参数,如username=zzhua password=1234
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        
        //6.准备环境变量
        //6.1 获取或者创建环境,配置环境
        //6.2 回调SpringApplicationRunListener.environmentPrepared(environment);表示环境准备完成
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        //6.3 配置ignore 的Bean信息
        configureIgnoreBeanInfo(environment);
        //7.打印Banner
        Banner printedBanner = printBanner(environment);
        //8.创建ApplicationContext,决定创建web容器还是普通的ioc,反射技术
        context = createApplicationContext();
        //9.异常信息处理
        exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                                                         new Class[] { ConfigurableApplicationContext.class }, context);
        //10.准备上下文环境
        //10.1 将environment保存到ioc容器中
        //10.2 applyInitializers(),回调前面保存的所有的ApplicationContextInitializer实现类的initialize()方法
        //10.3 回调所有的SpringApplicationRunListener.contextPrepared()
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        //11. spring容器的刷新 applicationContext).refresh(); 【如果是web应用还会创建嵌入式的Tomcat】。 其他章节已经整理
        refreshContext(context);
        
        //空方法,让子类实现
        afterRefresh(context, applicationArguments);
        //12.监控结束,并打印花费时间日志
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        //13.所有的SpringApplicationRunListener回调started()方法,表示容器开启完成
        listeners.started(context);
        //14
        //14.1 在ioc容器中获取所有实现了ApplicationRunner和CommandLineRunner接口的类
        //14.2 先回调所有的ApplicationRunner.run()
        //14.3 再回调所有的CommandLineRunner.run()
        callRunners(context, applicationArguments);
    }catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }

    try {
        //回调SpringApplicationRunListener.running()
        listeners.running(context);
    }catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    //返回创建好的容器
    return context;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值