spring boot启动配置原理【重点】

    技术2022-08-01  66

    几个重要的事件回调机制

    配置在META-INF/spring.factories

    ApplicationContextInitializer SpringApplicationRunListener

    只需要放在ioc容器中

    ApplicationRunner CommandLineRunner

    启动流程:

    1、创建SpringApplication对象
    SpringApplication.class 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)); /判断当前是否一个web应用 this.webApplicationType = WebApplicationType.deduceFromClasspath(); //从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;然后保存起来 this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); //从类路径下找到ETA-INF/spring.factories配置的所有ApplicationListener this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); //从多个配置类中找到有main方法的主配置类 this.mainApplicationClass = this.deduceMainApplicationClass(); }

    2、运行run方法
    public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); //声明IOC容器 ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); //awt this.configureHeadlessProperty(); //获取SpringApplicationRunListeners;从类路径下META-INF/spring.factories SpringApplicationRunListeners listeners = this.getRunListeners(args); //回调所有的获取SpringApplicationRunListener.starting()方法 listeners.starting(); Collection exceptionReporters; try { //封装命令行参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //准备环境 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); //创建环境完成后回调SpringApplicationRunListener.environmentPrepared();表示环境准备完成 this.configureIgnoreBeanInfo(environment); //打印banner图标 Banner printedBanner = this.printBanner(environment); //创建ApplicationContext;决定创建web的ioc还是普通的ioc context = this.createApplicationContext(); //做异常分析报告 exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); //准备上下文环境;将environment保存到ioc中;而且执行applyInitializers(); //applyInitializers():回调之前保存的所有的ApplicationContextInitializer的initialize方法 //回调所有的SpringApplicationRunListener的contextPrepared() this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); //prepareContext运行完成以后回调所有的SpringApplicationRunListener的contextLoaded(); //刷新容器;ioc容器初始化(如果是web应用还会创建嵌入式的Tomcat);Spring注解版 //扫描,创建,加载所有组件的地方;(配置类,组件,自动配置) this.refreshContext(context); //从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调 //ApplicationRunner先回调,CommandLineRunner再回调 this.afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } //回调所有的SpringApplicationRunListener的started() listeners.started(context); this.callRunners(context, applicationArguments); } catch (Throwable var10) { this.handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); } try { //所有的SpringApplicationRunListener回调running方法 listeners.running(context); //整个SpringBoot应用启动完成以后返回启动的ioc容器; return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } }
    总结:

    创建SpringApplication对象

    保存主配置类

    判断当前是否时一个web应用

    从类路径下找到 META-INFO/spring.factories 配置的所有 ApplicationContextInitialize;

    类路径下找到 META-INFO/spring.factories 配置的所有 ApplicationListener

    从多个配置类中找到有main方法的主配置类

    运行 run 方法

    声明IOC容器从类路径下 META-INFO/spring.factories 获取 SpringApplicationRunListeners回调所有获取的 SpringApplicationRunListener.starting() 方法封装命令行参数准备环境;创建环境后完成回调 SpringApplicationRunListener.environmentPrepared(); 表示环境准备完成 (in wai le meng ci pei er)打印 banner 图标创建 ApplicationContext;决定创建 web 的 ioc 还是普通的 ioc做异常分析报告准备上下文环境,将 environment 保存到 ioc 中;而且执行 applyInitializers()【应用初始化】; 回调之前保存的所有 ApplicationContextInitializer 的 Initialize 方法;回调所有的 SpringApplicationRunListener 的 contextPrepared();prepareContext 运行完成后回调所有 SpringApplicationRunListener 的 contextLoaded()刷新容器;ioc 容器初始化(如果是web应用还会创建嵌入式的Tomcat);扫描,创建,加载所有组件的地方;从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调;ApplicationRunner先回调,CommandLineRunner再回调所有的 SpringApplicationRunListener回调 finished 方法整个 SpringBoot应用启动完成以后返回启动的 ioc 容器;
    3、事件监听机制

    配置在META-INF/spring.factories

    ApplicationContextInitializer

    public class HelloApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext applicationContext) { System.out.println("ApplicationContextInitializer...initialize..."+applicationContext); } }

    SpringApplicationRunListener

    package com.akieay.akieayblog.admin.listener; import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplicationRunListener; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.ConfigurableEnvironment; /** * @author admin */ public class HelloSpringApplicationRunListener implements SpringApplicationRunListener { //必须有的构造器 public HelloSpringApplicationRunListener(SpringApplication application, String[] args){ } @Override public void starting() { System.out.println("SpringApplicationRunListener...starting..."); } @Override public void environmentPrepared(ConfigurableEnvironment environment) { Object o = environment.getSystemProperties().get("os.name"); System.out.println("SpringApplicationRunListener...environmentPrepared.."+o); } @Override public void contextPrepared(ConfigurableApplicationContext context) { System.out.println("SpringApplicationRunListener...contextPrepared..."); } @Override public void contextLoaded(ConfigurableApplicationContext context) { System.out.println("SpringApplicationRunListener...contextLoaded..."); } @Override public void started(ConfigurableApplicationContext context) { System.out.println("SpringApplicationRunListener...started..."); } @Override public void running(ConfigurableApplicationContext context) { System.out.println("SpringApplicationRunListener...running..."); } @Override public void failed(ConfigurableApplicationContext context, Throwable exception) { System.out.println("SpringApplicationRunListener...failed..."); } }

    配置(META-INF/spring.factories)

    org.springframework.context.ApplicationContextInitializer=\ com.akieay.akieayblog.admin.listener.HelloApplicationContextInitializer org.springframework.boot.SpringApplicationRunListener=\ com.akieay.akieayblog.admin.listener.HelloSpringApplicationRunListener

    只需要放在ioc容器中

    ApplicationRunner

    @Component public class HelloApplicationRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("ApplicationRunner...run...."); } }

    CommandLineRunner

    @Component public class HelloCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("CommandLineRunner...run..."+ Arrays.asList(args)); } }
    Processed: 0.010, SQL: 9