springboot执行流程


构造方法初始化,创建一个新的实例,这个应用程序的上下文要从指定的来源加载bean
public SpringApplication(ResourceLoaderresourceLoader,Class<?>...primarySources){ this.sources=newLinkedHashSet(); this.bannerMode=Mode.CONSOLE; this.logStartupInfo=true; this.addCommandLineProperties=true; this.headless=true; this.registerShutdownHook=true; this.additionalProfiles=newHashSet(); 初始化资源加载器,默认为null this.resourceLoader=resourceLoader; 断言要加载的资源类不能为null否则报错 Assert.notNull(primarySources,"Primary Sources must not be null"); 初始化主要加载资源并去重 this.primarySources=newLinkedHashSet(Arrays.asList(primarySources)); 判断当前应用程序的类型 NONE/SERVLET/REACTIVE this.webApplicationType=this.deduceWebApplicationType(); 加载所有的初始化容器,设置应用上下文初始化器,从"META-INF/spring.factories"读取ApplicationContextInitializer类的实例名称集合并去重,并进行set去重。(一共5个) this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); 设置监听器,从"META-INF/spring.factories"读取ApplicationListener类的实例名称集合并去重,并进行set去重。(一共10个) this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); 推断主入口应用类,通过当前调用栈,获取Main方法所在类,并赋值给mainApplicationClass this.mainApplicationClass=this.deduceMainApplicationClass(); } 启动流程 springboot启动的运行方法,可以看到主要是各种运行环境的准备工作 public ConfigurableApplicationContext run(String...args){ 创建并启动计时监控类 设置当前任务的id和启动的时间,方便后续的时候进行计时的操作 StopWatch stopWatch=new StopWatch(); stopWatch.start(); 初始化上下文 初始化异常报告集合 ConfigurableApplicationContext context=null; Collection<SpringBootExceptionReporter> exceptionReporters=new ArrayList(); 设置系统属性“java.awt.headless” 默认为true,用于运行headless服务器,进行简单的图像处理,多用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true this.configureHeadlessProperty(); 注册linsteners,创建所有spring运行监听器并发布应用启动事件,简单说的话就是获取SpringApplicationRunListener类型的实例(EventPublishingRunListener对象),并封装进SpringApplicationRunListeners对象,然后返回这个SpringApplicationRunListeners对象。说的再简单点,getRunListeners就是准备好了运行时监听器EventPublishingRunListener。 记载spring.factoris文件中的你内容 获取文件中对应类的全路径 根据反射得到具体的实体类对象 生成对应的对象之后再返回给调用者 SpringApplicationRunListeners listeners=this.getRunListeners(args); 每次监听器在实际做操作的时候都会执行listeners.starting() this.initialMulticaster.multicastEvent 匹配不同类型的事件,然后从所有的监听器中把不符合条件的监听给过滤掉 符合条件的监听器会循环执行具体的自己的处理逻辑 listeners.starting(); try{ 初始化默认参数应用类 加载命令行的参数值,解析在命令行中通过--key=value输入的属性值,封装到ApplicationArguments对象中 ApplicationArguments applicationArguments=new DefaultApplicationArguments(args); 根据运行监听器和应用参数来准备spring环境 ConfigurableEnvironment environment=this.prepareEnvironment(listeners,applicationArguments); 设置系统属性,保证某些bean不会添加到准备的环境中(设置忽略的参数) this.configureIgnoreBeanInfo(environment); 创建banner打印类 Banner printedBanner=this.printBanner(environment); 创建应用上下文对象,根据当前应用类型选择创建什么类型的上下文 servlet,reactive,none context=this.createApplicationContext(); 设置异常报告对象,用来支持报告关于启动的错误 this.getSpringFactoriesInstances(SpringBootExceptionReporter.class,newClass[]{ConfigurableApplicationContext.class},context); 准备当前上下文对象,包含一个关键操作,将启动类注入容器,为后续开启自动化提供基础 设置初始化进行执行,向beanfactory中注入了三个postprocessor的对象,后续在自动装配的时候会用到applyInitializers(context); listeners.contextPrepared(context); 加载很多资源配置,自动装配在此环节完成load(context, sources.toArray(new Object[0])); listeners.contextLoaded(context); this.prepareContext(context,environment,listeners,applicationArguments,printedBanner); 刷新应用上下文 this.refreshContext(context); 应用上下文刷新后置操作做一些扩展功能 this.afterRefresh(context,applicationArguments); 计时结束,并打印程序所用时长 stopWatch.stop(); 输出日志,记录执行的主类目和事件信息 if(this.logStartupInfo){ (newStartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(),stopWatch); } 启动所有的监听器对象 listeners.started(context); 执行所有的runner运行器 this.callRunners(context,applicationArguments); }catch(Throwablevar9){ 处理失败的操作 this.handleRunFailure(context,listeners,exceptionReporters,var9); thrownewIllegalStateException(var9); } 启动完成调用,发布应用上下文就绪事件 listeners.running(context); 返回应用上下文 return context; }
原文地址:https://www.cnblogs.com/hikoukay/p/12164366.html