SpringBoot流程解析(二)

目录

SpringApplication::run

十一

十二

十三

十四

十五

十六

十七

十八


上篇分析完启动类注解和SpringApplication构造函数。

SpringApplication::run

启动一个spring应用,创建并刷新一个新的ApplicationContext

	public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
        // 一
		stopWatch.start();
        // 二
		ConfigurableApplicationContext context = null;
        // 三
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        // 四
		configureHeadlessProperty();
        // 五
		SpringApplicationRunListeners listeners = getRunListeners(args);
        // 六
		listeners.starting();
		try {
            // 七
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 八
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
            // 九
			configureIgnoreBeanInfo(environment);
            // 十
			Banner printedBanner = printBanner(environment);
            // 十一
			context = createApplicationContext();
            // 十二
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
            // 十三
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            // 十四
			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;
	}

是一个计时器工具类,这里先记录了项目的启动时间

初始化应用上下文

初始化异常报告器

设置java.awt.headless为true

为true的话是告知系统不要指望显示器、鼠标、键盘等可以正常运行,这是一个服务端程序,用到这些外设的时候需要靠自己模拟

我们点进来看

private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		return new SpringApplicationRunListeners(logger,
				getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
	}

我们又看到了getSpringFactoriesInstances这个方法(不记得的可以返回SpringBoot流程解析(一)去回顾),它把SpringApplicationRunListener作为key,取到的value是org.springframework.boot.context.event.EventPublishingRunListener(从spring.factories取得)。最后放入集合返回。

点进去

public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}

 先看initialMulticaster

在初始化EventPublishingRunListener时初始化了initialMulticaster

public EventPublishingRunListener(SpringApplication application, String[] args) {
   this.application = application;
   this.args = args;
   this.initialMulticaster = new SimpleApplicationEventMulticaster();
   for (ApplicationListener<?> listener : application.getListeners()) {
      this.initialMulticaster.addApplicationListener(listener);
   }
}

 再看new ApplicationStartingEvent(this.application, this.args)

构建了一个ApplicationStartingEvent

public EventObject(Object source) {
    if (source == null)
        throw new IllegalArgumentException("null source");

    this.source = source;
}

 最后看multicastEvent

先根据事件类型获取到合适的监听器,然后对这些合适的监听器遍历,每一个监听器都开启一个独立的线程去执行监听

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   Executor executor = getTaskExecutor();
   for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      if (executor != null) {
         executor.execute(() -> invokeListener(listener, event));
      }
      else {
         invokeListener(listener, event);
      }
   }
}

解析启动入参

解析配置环境,如配置文件、系统变量等并通过监听器广播环境变量准备完毕事件

默认设置spring.beaninfo.ignore系统属性为true。

保证某些bean不会添加到准备的环境中。

打印banner

十一

根据webApplicationType初始化spring上下文

十二

初始化配置的异常报告类

十三

准备上下文

主要分为6个步骤。

  • setEnvironment:设置上下文环境
  • postProcessApplicationContext:上下文后置处理,默认没做什么事。
  • applyInitializers:调用之前实例化的几个ApplicationContextInitializer类的initialize方法
  • contextPrepared:向listeners发送上下文已准备完毕的通知。
  • load:BeanDefinitionLoader可以加载各种bean,比如注解、XML、package等多种类型的bean,在后面利用BeanDefinitionLoader将这些beans都加载进上下文中。
  • contextLoaded:向listeners发送上下文已加载完毕的通知。

十四

刷新上下文(属于spring知识)

十五

空实现,自己可以自定义实现

十六

发布启动完成事件

十七

如果有ApplicationRunner或者CommandLineRunner类型的bean,则触发run函数,启动任务。

十八

监听应用上下文运行

猜你喜欢

转载自blog.csdn.net/wai_58934/article/details/126558544
今日推荐