咱们从主办法启动的入口开始,如下:
public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args);}
run办法次要干了两件事,一件是创立 SpringApplication 并进行初始化,初始化如下图:
另一件是run的执行,咱们重点看run的执行流程,一路点击run办法,直到:
这个就是run办法启动的主流程了,上面一步步来看:
创立秒表计时器,开始计时
StopWatch stopWatch = new StopWatch();stopWatch.start();
配置Headless属性
private void configureHeadlessProperty() { System.setProperty("java.awt.headless", System.getProperty("java.awt.headless", Boolean.toString(this.headless)));}
这里同一个属性,取了有设置回去,看起来截然不同,其实是因为 getProperty带两个参数的时候,会给默认值,所以再设置一次就能保障该属性都有值
从META-INF/spring.factories找到所有SpringApplicationRunListener的监听器,启动监听器
SpringApplicationRunListeners listeners = this.getRunListeners(args);listeners.starting(bootstrapContext, this.mainApplicationClass);
配置环境 ConfigurableEnvironment,退出到监听器对象中
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
点击prepareEnvironment办法进去,办法里首先创立环境对象:
ConfigurableEnvironment environment = this.getOrCreateEnvironment();
接着配置环境:
this.configureEnvironment((ConfigurableEnvironment)environment, applicationArguments.getSourceArgs());
而 configureEnvironment()办法,会进行以下两个操作:
// 加载配置源参数和命令行属性this.configurePropertySources(environment, args);// 配置以后activede的形容文件this.configureProfiles(environment, args);
回到prepareEnvironment办法:
筹备零碎环境:
listeners.environmentPrepared(bootstrapContext, (ConfigurableEnvironment)environment);
接下来bindToSpringApplication()办法:
protected void bindToSpringApplication(ConfigurableEnvironment environment) { try { Binder.get(environment).bind("spring.main", Bindable.ofInstance(this)); } catch (Exception var3) { throw new IllegalStateException("Cannot bind to SpringApplication", var3); } }
将配置文件中的spring.main结尾的配置信息绑定到SpringApplication类对应的属性中。
再回到run主流程中:
- configureIgnoreBeanInfo
设置疏忽掉的bean
接下来是打印 banner:
Banner printedBanner = this.printBanner(environment);
接着这一步比拟重要,就是创立容器:
context = this.createApplicationContext();
- 接下来是prepareContext办法
具体如下:
// 将环境变量设置到容器中context.setEnvironment(environment);// 对 ApplicationContext进行后置解决,设置beanNameGenerator、resourceLoader、classLoader和conversionServicethis.postProcessApplicationContext(context);// 获取之前获取到的所有 initializer 类型的类,并进行初始化this.applyInitializers(context);// 告诉监听器context筹备实现listeners.contextPrepared(context);// 打印profile信息this.logStartupProfileInfo(context); // 注册一个利用参数实例ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); beanFactory.registerSingleton("springApplicationArguments", applicationArguments);// 注册 printedBanner实例beanFactory.registerSingleton("springBootBanner", printedBanner);// 设置是否容许同名bean,默认false((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);// 获取,加载启动类,注入到容器中Set<Object> sources = this.getAllSources();this.load(context, sources.toArray(new Object[0]));//触发监听器,调用每个 SpringApplicationRunListerner 的 contextLoaded 办法listeners.contextLoaded(context);
refreshContext 刷新容器,实现组件的扫描、创立、加载等
this.refreshContext(context);
返回容器
return context;
总流程图如下: