springboot中SpringApplication的run方法
本篇内容介绍了"springboot中SpringApplication的run方法"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
SpringApplication的run方法解析
public ConfigurableApplicationContext run(String... args) { // 构造一个任务执行观察器(Java 查看时间和性能的类) StopWatch stopWatch = new StopWatch(); // 开始执行,记录开始时间 stopWatch.start(); // 定制配置上下文,顶级父类包含Bean Factory ConfigurableApplicationContext context = null; // 定义一个错误集合(用来支持报告关于启动的错) CollectionexceptionReporters = new ArrayList<>(); //定义一个 awt 的headless(设置headless模式,名字为 java.awt.headless 的系统属性设置为true) configureHeadlessProperty(); // 获取一个run监听器,主要监听SpringApplication对象,(内部只有一个EventPublishingRunListener) SpringApplicationRunListeners listeners = getRunListeners(args); //调用监听器的启动,当SpringApplication对象的run方法刚启动的时候(依靠SimpleApplicationEventMulticaster) listeners.starting(); try { // 构造一个应用程序参数持有类 应用参数化 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //创建并配置Environment(该过程会获取入参、加载application配置文件),配置环境(Environment)加入到监听器对象中(SpringApplicationRunListeners) ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); // 配置bean的忽略信息 扫描 pring.beaninfo.ignore 进行属性读取 可选true/false (在application文件中配置) configureIgnoreBeanInfo(environment); //打印logo 即pringboot的beaninfo.ignore样图 Banner printedBanner = printBanner(environment); // 根据应用类型创建对应的Context容器 初始化bean *** context = createApplicationContext(); // 从配置文件中获取具体是实现类 exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); // 刷新Context之前的准备 即准备使用上下文 // 将SpringApplicationRunListeners、ConfigurableEnvironment、ApplicationArguments、Banner等重要组件雨上下文对象关联 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 刷新Context容器 *** // 实现spring-boot-starter-*(mybatis、redis等)自动化配置的关键,包括spring.factories的加载,bean的实例化等核心工作 refreshContext(context); // 刷新Context容器之后处理 afterRefresh(context, applicationArguments); // 执行结束,记录执行时间 stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass) .logStarted(getApplicationLog(), stopWatch); } // Context容器刷新完毕发布,这里接受ApplicationStartedEvent事件的listener会执行相应的操作 //【Spring容器已经刷新过且应用已经启动,但是CommandLineRunners和ApplicationRunners还未调用,直接通过spring容器自己发送 // (因为ApplicationListener已经加入spring容器)】 listeners.started(context); // 触发Context容器refresh完以后的执行 唤醒运行线程 callRunners(context, applicationArguments); } catch (Throwable ex) { // 启动错误报告处理 handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { // Context启动完毕,Runner运行完逼发布,这里接受ApplicationStartedEvent事件的listener会执行相应的操作 //【已经调用了CommandLineRunners,直接通过spring容器自己发送(因为ApplicationListener已经加入spring容器)】 listeners.running(context); } catch (Throwable ex) { // 启动错误报告处理 handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } // 返回Spring容器 return context;}
返回的对象 ConfigurableApplicationContext 就是 applicationContext 子类,前者相比后者提供了更多的功能,比如实现 Lifecycle, Closeable 接口 更好的管理bean的声明周期,还有其他的 诸如:addBeanFactoryPostProcessor,setParent,setId,addApplicationListener,addProtocolResolver 等额外的功能。
创建并启动观察器
设置 java.awt.headless 系统变量
加载所有 classpath 下的 META-INF/spring.factories 中的 SpringApplicationRunListener
依次调用的 SpringApplicationRunListener 的 starting 方法,发布 springboot 启动事件
实例化 ApplicationArguments 对象 获取应用参数
创建 ConfigurableEnvironment 对象 environment
注意 webApplicationType 控制创建的 Environment 对象的类型,当为 SERVLET 时为 StandardServletEnvironment.class,当为 REACTIVE 时为 StandardReactiveWebEnvironment.class,其余为 StandardEnvironment.class
配置 environment 对象,主要把方法参数配置到 environment 中--通过 configurePropertySources(environment, args) 设置 properties ,通过 configureProfiles(environment, args) 设置 profiles
执行所有 SpringApplicationRunListeners 的 environmentPrepared 方法发布 environmentPrepared 事件,即调用 实现ApplicationListener接口 ConfigFileApplicationListener 的 onApplicationEvent 事件
注意 该事件获取 EnvironmentPostProcessor类型的工厂类实例集合,并将ConfigFileApplicationListener实例追加入该集合,遍历该实例集合 一次执行postProcessEnvironment方法 分别设置 environment的propertySource属性中的systemEnvironment属性、propertySourceList属性、加载YML配置文件
即把当前的 environment 和当前的 springApplication 绑定
将 ConfigurationPropertySource 放入 environment 的 propertysource 中的第一个
打印 Banner
创建Spring容器
从配置文件中获取具体异常实现类
设置spring容器的 environment
当 beanNameGenerator 属性存在,向bean工厂中注册 beanNameGenerator; 当resourceLoader属性存在,如果 context 实现GenericApplicationContext 则把其赋值给上下文中的 resourceLoader 属性,如果 context 实现DefaultResourceLoader 则获取其加载器,赋值给上下文中的 classLoader 属性
回调 ApplicationContextInitializer 的 initialize 方法来初始化 context,其中还检测各个 ApplicationContextInitializer 是否接受该类型的容器
注意 其在 context 中注册两个监听器'ConditionEvaluationReportListener'和'ServerPortInfoApplicationContextInitializer',同时也在 context 中注册两个bean工厂后置处理器'CachingMetadataReaderFactoryPostProcessor'和'ConfigurationWarningsPostProcessor'
执行所有 SpringApplicationRunListener 的 contextPrepared 方法,但目前是个空实现
context 中分别注册 springApplicationArguments 和 springBootBanner 这两个单例bean
获取我们的 primarySources 和 sources 加载注册到context中的 beanFactory里,即注册主类到beanFactory
执行所有 SpringApplicationRunListener 的 contextLoaded 方法,首先判断 ApplicationListener 是否属于 ApplicationContextAware,如果是的话就将spring容器赋值给该 listener,然后将该 ApplicationListener 赋值给spring容器,然后调用 ApplicationListener 的 onApplicationEvent 方法
注意 该处向context注册了10个监听器(listeners属性的值)和一个bean工厂后置处理器'PropertySourceOrderingPostProcessor',并注册了一个单例bean(SpringBootloggingSystem)
调用 AbstractApplicationContext 的 refresh 方法刷新Spring容器
设置些初始的操作(开启激活,启动日期,初始化propertySource)、配置工厂的标准上下文特征、注册 BeanPostProcessor 和 BeanFactoryPostProcessor(前者实现对bean初始化前后进行设置,后实现对 beanFactory 进行修改 或对 beanDefinition 进行修改或者增加或者初始化渴望提前初始化的 bean)、初始化国际化文件、初始化web容器、实例化非懒加载的剩余 bean 等等操作
调用 AbstractApplicationContext 的 registerShutdownHook 方法,注册一个线程该线程主要指向 doclose 方法
执行所有 SpringApplicationRunListener 的 started 方法,发布 started 事件
回调 callrunners 方法从spring容器中获取 ApplicationRunner 和 CommandLineRunner 对象,然后按照顺序排序,循环调用他们的 run 方法
执行所有 SpringApplicationRunListener 的 running 方法,发布 running 事件
第五步到二十五步执行过程中出现异常调用 handleRunFailure 方法处理不同的异常状态异常,调用 listeners.failed(context, exception),并关闭spring容器
"springboot中SpringApplication的run方法"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!