SpringBoot - 启动配置原理(启动原理,运行流程)

springboot启动流程主要有下面几步:SpringBoot - 启动配置原理(启动原理,运行流程)_第1张图片
几个重要的事件回调机制:

配置在META-INF/spring.factories:

ApplicationContextInitializer
SpringApplicationRunListener

只需要放在ioc容器中

ApplicationRunner
CommandLineRunner

启动流程

主启动类

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

run方法分为两步

在这里插入图片描述

  1. 创建SpringApplication对象

    源码: 每一步都是追踪源码 注释

    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;然后保存
    		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    		// 从类路径下找到ETA‐INF/spring.factories配置的所有ApplicationListener,保存
    		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    		// //从多个配置类中找到有main方法的主配置类
    		this.mainApplicationClass = deduceMainApplicationClass();
    	}
    

    创建SpringApplication对象时加载的ApplicationContextInitializer:
    SpringBoot - 启动配置原理(启动原理,运行流程)_第2张图片
    创建SpringApplication对象时加载的ApplicationListener:SpringBoot - 启动配置原理(启动原理,运行流程)_第3张图片

  2. 运行run方法
    源码: 每一步都是追踪源码 注释

    public ConfigurableApplicationContext run(String... args) {
    	StopWatch stopWatch = new StopWatch();
    	stopWatch.start();
    	// 声明IOC容器
    	ConfigurableApplicationContext context = null;
    	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    	configureHeadlessProperty();
    	 // 获取SpringApplicationRunListeners;从类路径下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);
    		// 打印spring的图标
    		Banner printedBanner = printBanner(environment);
    		// 创建ApplicationContext;决定创建web的ioc还是普通的ioc
    		context = createApplicationContext();
    		// 做异常记录
    		exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
    				new Class[] { ConfigurableApplicationContext.class }, context);
    		// 准备上下文环境, 将environment保存到ioc中;
    		// applyInitializers():回调之前保存的所有的ApplicationContextInitializer的initialize方法
    		// 回调所有的SpringApplicationRunListener的contextPrepared();
    		// prepareContext运行完成以后回调所有的SpringApplicationRunListener的contextLoaded();
    		prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    
    		// 刷新容器;ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat)
    		// 扫描,创建,加载所有组件的地方;(配置类,组件,自动配置)
    		refreshContext(context);
    		
    		// 从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
    		// ApplicationRunner先回调,CommandLineRunner再回调
    		afterRefresh(context, applicationArguments);
    		stopWatch.stop();
    		if (this.logStartupInfo) {
    			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
    		}
    		// 所有的SpringApplicationRunListener回调finished方法
    		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);
    	}
    	// 整个SpringBoot应用启动完成以后返回启动的ioc容器;
    	return context;
    	}
    

run 方法的主要步骤点,和回调机制

  1. 从类路径下META‐INF/spring.factories 获取 SpringApplicationRunListeners
  2. 回调所有的获取SpringApplicationRunListener.starting()方法
  3. 准备环境prepareEnvironment()
  4. 创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成
  5. 准备上下文环境prepareContext() :
    将environment保存到ioc中;
    回调之前保存的所有的ApplicationContextInitializer的initialize方法;
    回调所有的SpringApplicationRunListener的contextPrepared();
    prepareContext运行完成以后回调所有的SpringApplicationRunListener的contextLoaded();
  6. refreshContext(context); 刷新容器,ioc容器初始化。扫描,创建,加载所有组件的地方;(配置类,组件,自动配置)
  7. 从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
  8. 所有的SpringApplicationRunListener回调finished方法

你可能感兴趣的:(SpringBoot)