8.1、SpringBoot启动流程--把spring应用跑起来

把spring应用跑起来 开始进入run方法:

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

step into run()
public ConfigurableApplicationContext run(String... args) { //停止监听器,监控整个应用的启动和停止的 StopWatch stopWatch = new StopWatch(); //start方法里的源码可以看下面代码展示 stopWatch.start(); //记录应用的启动时间 //创建引导上下文(xxxContext都是引导环境) DefaultBootstrapContext bootstrapContext = createBootstrapContext(); //createBootstrapContext方法的源码在下面 ConfigurableApplicationContext context = null; //让当前应用进入headless模式。源码在下面 //(headless是自力更生的意思,不依赖别人) configureHeadlessProperty(); //获取所有RunListener(运行监听器)保存到SpringApplicationRunListeners //【为了方便所有Listener进行事件感知】所谓的监听器就是监听到当前项目的状态 SpringApplicationRunListeners listeners = getRunListeners(args); //starting()源码分析在下面 listeners.starting(bootstrapContext, this.mainApplicationClass); try { //准备ApplicationArguments应用参数,应用参数是从命令行里传过来的。即保存命令行参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //准备运行时环境 ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); //这行代码结束后,所有的环境信息已经准备就绪 //配置一些要忽略的bean信息 configureIgnoreBeanInfo(environment); //打印banner(banner是啥,可以看下面) Banner printedBanner = printBanner(environment); //创建ioc容器(容器创建完成后,所有的bean都会进去) context = createApplicationContext(); //源码在下面 //把Startup信息保存起来 context.setApplicationStartup(this.applicationStartup); //准备ioc容器环境的信息(源码在下面) prepareContext(bootstrapContext, 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, listeners); throw new IllegalStateException(ex); }try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, null); throw new IllegalStateException(ex); } return context; }

【8.1、SpringBoot启动流程--把spring应用跑起来】8.1、SpringBoot启动流程--把spring应用跑起来
文章图片

banner:
._______ _ _ /\\ / ___'_ __ _ _(_)_ ____ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/___)| |_)| | | | | || (_| |) ) ) ) '|____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot ::(v2.4.0)

start方法里的源码
public void start() throws IllegalStateException { this.start(""); }public void start(String taskName) throws IllegalStateException { if (this.currentTaskName != null) { throw new IllegalStateException("Can't start StopWatch: it's already running"); } else { //给stopWatch对象保存一些信息 this.currentTaskName = taskName; //当前任务的名字 this.startTimeNanos = System.nanoTime(); //当前的时间 }

createBootstrapContext创建引导上下文
private DefaultBootstrapContext createBootstrapContext() { //创建默认的引导上下文对象 //以后就会给里面保存很多信息 DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext(); //遍历所有之前的获取到的bootstrappers,调用每一个bootstrappers的intitialize() 来完成对引导启动器上下文环境设置 this.bootstrappers.forEach((initializer) -> initializer.intitialize(bootstrapContext)); return bootstrapContext; //null } ============================================================= public interface Bootstrapper {/** * Initialize the given {@link BootstrapRegistry} with any required registrations. * @param registry the registry to initialize */ //传入引导注册工厂 //这个工厂里面可以给他加入一些当前上下文的一些引导环境信息 void intitialize(BootstrapRegistry registry); }

让当前应用进入headless模式
private void configureHeadlessProperty() { System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless))); }

获取所有RunListener(运行监听器)
所谓的监听器就是监听到当前项目的状态
private SpringApplicationRunListeners getRunListeners(String[] args) { Class[] types = new Class[] { SpringApplication.class, String[].class }; //new SpringApplicationRunListeners:相当于把找到的Listener保存到SpringApplicationRunListener; return new SpringApplicationRunListeners(logger, //getSpringFactoriesInstances: 去spring.factories找SpringApplicationRunListener getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup); }===================================================== SpringApplicationRunListeners(Log log, Collection listeners, ApplicationStartup applicationStartup) { this.log = log; this.listeners = new ArrayList<>(listeners); this.applicationStartup = applicationStartup; }List listeners;

8.1、SpringBoot启动流程--把spring应用跑起来
文章图片

starting():
遍历所有的SpringApplicationRunListener调用 starting 方法;相当于通知所有感兴趣系统正在启动过程的人,项目正在 starting。(即告诉我这个项目正在启动)
void starting(ConfigurableBootstrapContext bootstrapContext, Class mainApplicationClass) { doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext), (step) -> { if (mainApplicationClass != null) { step.tag("mainApplicationClass", mainApplicationClass.getName()); } }); }========================================= 进入doWithListeners方法: private void doWithListeners(String stepName, Consumer listenerAction, Consumer stepAction) { StartupStep step = this.applicationStartup.start(stepName); //遍历所有的listeners,现在进行到哪一步了,相当于一个事件信息 this.listeners.forEach(listenerAction); if (stepAction != null) { stepAction.accept(step); } step.end(); }================================ 进入this.listeners.forEach(listenerAction): void starting(ConfigurableBootstrapContext bootstrapContext, Class mainApplicationClass) { //遍历所有的SpringApplicationRunListener调用starting方法 doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext), (step) -> { if (mainApplicationClass != null) { step.tag("mainApplicationClass", mainApplicationClass.getName()); } }); }

准备环境 :
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) { // Create and configure the environment //如果当前有上下文环境信息,就获取并返回;没有就创建 //比如保存底层运行的环境变量 ConfigurableEnvironment environment = getOrCreateEnvironment(); //配置环境(拿到环境信息,命令行参数) configureEnvironment(environment, applicationArguments.getSourceArgs()); //绑定环境信息 ConfigurationPropertySources.attach(environment); //监听器调用 listener.environmentPrepared();通知所有的监听器当前环境准备完成 listeners.environmentPrepared(bootstrapContext, environment); //将环境信息设置到类的最后(这个不用管) DefaultPropertiesPropertySource.moveToEnd(environment); //配置额外的Profiles,激活哪些环境(不用管) configureAdditionalProfiles(environment); //绑定工作(都是找到一些东西,把一些属性绑定到某个值里面) bindToSpringApplication(environment); //又是准备一些环境信息 if (!this.isCustomEnvironment) { environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass()); } //准备完了后,把环境信息再次绑定 ConfigurationPropertySources.attach(environment); return environment; }

    推荐阅读