SpringBoot之ApplicationRunner解析(spring容器启动完成执行的类)
SpringBoot ApplicationRunner解析
在项目中,可能会遇到这样一个问题:在项目启动完成之后,紧接着执行一段代码。
在SpringBoot中,提供了一个接口:ApplicationRunner。
该接口中,只有一个run方法,他执行的时机是:spring容器启动完成之后,就会紧接着执行这个接口实现类的run方法。
@Component public class PublishEndpoint implements ApplicationRunner{ @Override public void run(ApplicationArguments applicationArguments) throws Exception { //do something } }
这里有几点说明:
- 这个实现类,要注入到spring容器中,这里使用了@Component注解;
- 在同一个项目中,可以定义多个ApplicationRunner的实现类,他们的执行顺序通过注解@Order注解或者再实现Ordered接口来实现。
- run方法的参数:ApplicationArguments可以获取到当前项目执行的命令参数。(比如把这个项目打成jar执行的时候,带的参数可以通过ApplicationArguments获取到);
- 由于该方法是在容器启动完成之后,才执行的,所以,这里可以从spring容器中拿到其他已经注入的bean。
@SpringBootApplication启动流程详解
带你深入探索SpringApplication执行流程
SpringApplication的run方法的实现是我们本次探索之旅的主要线路,该方法的主要流程归纳如下:
1:如果我们使用的是SpringApplication的静态run方法,那么,这个方法里面首先要创建一个SpringApplication对象实例,然后调用这个创建好的SpringApplication的实例方法。在SpringApplication实例初始化的时候,它会提前做几件事情:
- 根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该创建一个为Web应用使用的ApplicationContext类型。
- 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
- 使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
- 推断并设置main方法的定义类。
2: SpringApplication实例初始化完成并且完成设置后,就开始执行run方法的逻辑了,方法执行伊始,首先遍历执行所有通过SpringFactoriesLoader可以查找到并加载的SpringApplicationRunListener。调用它们的started()方法,告诉这些SpringApplicationRunListener,“嘿,SpringBoot应用要开始执行咯!”。
3: 创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
4:遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,告诉他们:“当前SpringBoot应用使用的Environment准备好了咯!”。
5:如果SpringApplication的showBanner属性被设置为true,则打印banner。 【banner:英文广告横幅,在这里面指的是运行时输出的SpringBoot,还可以进行修改】
6: 根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成,然后根据条件决定是否添加ShutdownHook,决定是否使用自定义的BeanNameGenerator,决定是否使用自定义的ResourceLoader,当然,最重要的,将之前准备好的Environment设置给创建好的ApplicationContext使用。 【ShutdownHook :停止服务】
7: ApplicationContext创建好之后,SpringApplication会再次借助Spring-FactoriesLoader,查找并加载classpath中所有可用的ApplicationContext-Initializer,然后遍历调用这些ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理。
8:遍历调用所有SpringApplicationRunListener的contextPrepared()方法。
9:最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
10:遍历调用所有SpringApplicationRunListener的contextLoaded()方法。
11:调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序。
12:查找当前ApplicationContext中是否注册有CommandLineRunner,如果有,则遍历执行它们。
13: 正常情况下,遍历执行SpringApplicationRunListener的finished()方法、(如果整个过程出现异常,则依然调用所有SpringApplicationRunListener的finished()方法,只不过这种情况下会将异常信息一并传入处理)
去除事件通知点后,整个流程如下:
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
SpringBoot中使用Redis Stream实现消息监听示例
本文主要介绍了SpringBoot中使用Redis Stream实现消息监听示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2022-06-06idea项目启动报错,日志包冲突slf4j和logback冲突问题
遇到SLF4J冲突时,可以尝试移除冲突的绑定或调整项目依赖,具体方法包括删除多余的Logger绑定库,如Logback或Log4j,或在项目配置文件中明确指定使用的日志框架,若使用WebLogic服务器,需在weblogic.xml中进行特定配置,适当调整pom.xml文件中的依赖版本也可能解决问题2024-09-09JDK源码之线程并发协调神器CountDownLatch和CyclicBarrier详解
我一直认为程序是对于现实世界的逻辑描述,而在现实世界中很多事情都需要各方协调合作才能完成,就好比完成一个平台的交付不可能只靠一个人,而需要研发、测试、产品以及项目经理等不同角色人员进行通力合作才能完成最终的交付2022-02-02
最新评论