SpringBoot 启动配置原理

几个重要的事件回调机制

  • ApplicationContextInitializer
  • SpringApplicationRunListener
  • ApplicationRunner
  • CommandLineRunner

启动流程:

  1. 创建SpringApplication对象
    /**
     * 在springboot 2以前:
     * 调用initialize(source);
     * 在springboot 2以后,跳过了initialize()方法,直接调用run()方法
     */
    
    private void initialize(Object[] source){
        // 保存主配置类
        if(sources != null && source.length > 0){
            this.sources.addAll(Arrays.asList(sources));
        }
        // 判断当前是否是一个web应用
        this.webEnvironment = deduceWebEnvironment();
        // 从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来
        setInitializes((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        // 从类路径下找到META-INF/spring.factories配置的所有ApplicationListener;然后保存起来
       setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        // 从多个配置类中找到有main方法的主配置类
        this.mainApplicationClass = deduceMainApplicationClass();
    }
  2. 运行run方法
    public ConfigurableApplicationContext run(String... args) {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            ConfigurableApplicationContext context = null;
            Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
            configureHeadlessProperty();
            
            // 获取SpringApplicationRunListener;从类路径下META-INF/spring.factories找到
            SpringApplicationRunListeners listeners = getRunListeners(args);
            // 回调所有的SpringApplicationRunListener.starting()方法
            listeners.starting();
            try {
                // 封装命令行参数
                ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
                // 准备环境
                ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
                // 创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成
                configureIgnoreBeanInfo(environment);
                Banner printedBanner = printBanner(environment);
                
                // 创建ApplicationContext;决定创建web的ioc还是普通的ioc
                context = createApplicationContext();
                exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                        new Class[] { ConfigurableApplicationContext.class }, context);
                // 准备上下文环境;将environment保存到ioc中
                // applyInitializers();回调之前保存的所有的SpringApplicationRunListener的initializers方法
                
                prepareContext(context, environment, listeners, applicationArguments, printedBanner);
                // 回调所有的SpringApplicationRunListener的contextPrepared();
                // 刷新容器;ioc容器初始化完成
                refreshContext(context);
                afterRefresh(context, applicationArguments);
                stopWatch.stop();
                if (this.logStartupInfo) {
                    new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
                }
                listeners.started(context);
                callRunners(context, applicationArguments);
            }
            catch (Throwable ex) {
                handleRunFailure(context, ex, exceptionReporters, listeners);
                throw new IllegalStateException(ex);
            }
    
            try {
                listeners.running(context);
            }
            catch (Throwable ex) {
                handleRunFailure(context, ex, exceptionReporters, null);
                throw new IllegalStateException(ex);
            }
            return context;
        }

猜你喜欢

转载自www.cnblogs.com/luo-jian/p/12919111.html