目录
上篇分析完启动类注解和SpringApplication构造函数。
启动一个spring应用,创建并刷新一个新的ApplicationContext
- public ConfigurableApplicationContext run(String... args) {
- StopWatch stopWatch = new StopWatch();
- // 一
- stopWatch.start();
- // 二
- ConfigurableApplicationContext context = null;
- // 三
- Collection
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个步骤。
刷新上下文(属于spring知识)
空实现,自己可以自定义实现
发布启动完成事件
如果有ApplicationRunner或者CommandLineRunner类型的bean,则触发run函数,启动任务。
监听应用上下文运行