Spring Boot启动流程

随着我们ctrl加鼠标左键的使用,最终我们会在一个springboot项目中发现启动过程由以下两个过程组成

构造过程:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        //有些会指定额外的classpath目录,会有传入这个东西的情况
        //比如写入了一大堆配置文件,放在某处,那么启动时需要传入一个这个东西来识别自己的路径
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		//启动主类的class 对象
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		通过自己加载的类中含有哪个类型的dispatcher来判断是哪种web应用类型
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		//我们写一个spring boot的 starter,需要在其中加入一个spring.factories文件,
		//这一步就加载我们实现的那些Listenner也好Initializer也好,就是容器启动时,外部starter需要做的工作
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		//获取主类的方式,机巧,可以一学
		this.mainApplicationClass = deduceMainApplicationClass();
	}

run方法:

public ConfigurableApplicationContext run(String... args) {
        //这个是个秒表,用来告诉你boot过程花了多少时间
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		//有些情况下需要无显示器启动,这是对这个无显示器的情况进行的一些设置
		configureHeadlessProperty();
		//创建一组Listenner用来处理启动参数,也就是说启动参数是通过构造Listenner来实现的
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//Listnner开始监听一些启动事件
		listeners.starting();
		try {
		    //构造启动参数对象
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			//设置启动环境,所谓环境就是一些环境变量的集合,这里的环境变量就是一些启动参数
			ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
			//处理启动参数中要求我们忽略的bean
			configureIgnoreBeanInfo(environment);
			//就是banner,就是启动时那个Spring的logo,还带一片叶子
			Banner printedBanner = printBanner(environment);
			//这个很重要,加载了Context,从此我们有了容器这个东西,在spring boot的中,是一个基于注解的上下文
			context = createApplicationContext();
			//取得一个错误处理的一个什么东西
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			//这个也很重要,让我们的容器准备好,大概做了以下事情
			//1. 设置了上面的“环境”
			//2. 一些设置,其中包括resourceLoader的设置
			//3. 把之前加载的initializer全部执行他们的initialize()方法
			//4. 环境变量产生的Listenner,即上述的listeners,知会contextPrepared事件
			//5. 把参数作为一个bean放在容器中
			//6. 把banner作为一个bean放在容器中
			//7. 通过load方法生成一个BeanDefinitionLoader,这个是用来解析我们的自定义Bean的
			prepareContext(context, environment, listeners, applicationArguments,printedBanner);
			//刷新我们的容器,销毁原有的beanfactory,重新生成beanfactory以及生成所有的BeanDefinitions
			//beanfactory和BeanDefinition是干什么用的,这个就是经典的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;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值