快速了解SpringBoot启动流程分析

昨天无意之间看到了一家公司对于springboot的面试题,自己回来之后也就翻了翻源码,做了一个小整理。
在翻源码之前我们先要了解几个类
ApplicationContextInitializer Context初始化后调用的类
SpringApplicationRunListener SpringBoot运行监听的类

ApplicationRunner
CommandLineRunner
上面这两个几乎可以等价,用于启动后做客户自定义的操作
首先我们先来定义几个类方便我们分析

新建java类CustomCommandLineRunner类

@Component
public class CustomCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("CustomCommandLineRunner.run()执行了"+ Arrays.asList(args));
    }
}

新建java类CustomApplicationRunner

@Component
public class CustomApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("CustomApplicationRunne.run()执行了");
    }
}

新建java类CustomApplicationContextInitializer

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

新建java类CustomSpringApplicationRunListener

public class CustomSpringApplicationRunListener implements SpringApplicationRunListener {

 //必须有的构造器
    public CustomSpringApplicationRunListener (SpringApplication application, String[] args){

}

    @Override
    public void starting() {
        System.out.println("CustomSpringApplicationRunListener.starting()执行了");
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        System.out.println("CustomSpringApplicationRunListener.environmentPrepared()执行了");
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println("CustomSpringApplicationRunListener.contextPrepared()执行了");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("CustomSpringApplicationRunListener.contextLoaded()执行了");
    }

    @Override
    public void started(ConfigurableApplicationContext context) {
        System.out.println("CustomSpringApplicationRunListener.started()执行了");
    }

    @Override
    public void running(ConfigurableApplicationContext context) {
        System.out.println("CustomSpringApplicationRunListener.running()执行了");
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("CustomSpringApplicationRunListener.failed()执行了");
    }
}

在resources/META-INF/spring.factories增加

org.springframework.context.ApplicationContextInitializer=\
com.naver.listener.CustomApplicationContextInitializer

org.springframework.boot.SpringApplicationRunListener=\
com.naver.listener.CustomSpringApplicationRunListener

为什么如此,后面源代码分析
我们跟踪SpringBoot的启动类

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

其实SpringBoot启动就着两个步骤,先创建ConfigurableApplicationContext ,然后再调用Run方法。

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		//保存主类
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		//判断当前是什么类型项目
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
	//从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
	//从类路径下找到META-INF/spring.factories配置的所有ApplicationListener
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
}

可见着一步非常简单,只是把一些相关的类都加载了而已,并没执行
真的重要是run方法

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		//从类路径下META‐INF/spring.factories,取得SpringApplicationRunListeners;
		SpringApplicationRunListeners listeners = getRunListeners(args);
	//回调所有的获取SpringApplicationRunListener.starting()方法
		listeners.starting();
		try {
		    //封装命令行参数
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
		    //准备环境
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			configureIgnoreBeanInfo(environment);
            //创回调SpringApplicationRunListener.environmentPrepared();
//表示环境准备完成

			//打印Banner 
			Banner printedBanner = printBanner(environment);
            //根据环境创建context
			context = createApplicationContext();
		    //错误的异常报表
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
     //准备上下文环境;
//将environment保存到ioc中;
//applyInitializers()调用所有的ApplicationContextInitializer的initialize方法
//调用所有的SpringApplicationRunListener的contextPrepared();
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
//SpringApplicationRunListener的contextLoaded
//刷新容器
//扫描,创建,加载所有组件;
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			//所有的SpringApplicationRunListener回调started方法
			listeners.started(context);
			//获取所有的ApplicationRunner和CommandLineRunner进行调用
			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;
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值