SpringBoot的重要类及接口
ApplicationContextInitializer
首先看spring官网的介绍:
翻译下来就是说:
- 用于在spring容器刷新之前初始化Spring ConfigurableApplicationContext的回调接口。(就是在容器刷新之前调用该类的 initialize 方法。并将 ConfigurableApplicationContext 类的实例传递给该方法)
- 通常用于需要对应用程序上下文进行编程初始化的web应用程序中。例如,根据上下文环境注册属性源或激活配置文件等。
- 可排序的(实现Ordered接口,或者添加@Order注解)
ApplicationContextInitializer三种实现方式
首先新建一个类 MyApplicationContextInitializer并实现 ApplicationContextInitializer 接口。
public class MyApplicationContextInitializer implements ApplicationContextInitializer { @Override public void initialize(ConfigurableApplicationContext applicationContext) { System.out.println("-----MyApplicationContextInitializer initialize-----"); } }
1、main函数中添加
@SpringBootApplication public class MySpringBootApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(MySpringBootApplication.class); application.addInitializers(new MyApplicationContextInitializer()); application.run(args); } }
2、配置文件中配置
context.initializer.classes=org.springframework.boot.demo.common.MyApplicationContextInitializer
3、SpringBoot的SPI扩展---META-INF/spring.factories中配置
org.springframework.context.ApplicationContextInitializer=org.springframework.boot.demo.common.MyApplicationContextInitializer
排序问题
给 MyApplicationContextInitializer 加上Order注解:我们指定其拥有最高的排序级别。(值越小越早执行)
@Order(Ordered.HIGHEST_PRECEDENCE) public class MyApplicationContextInitializer implements ApplicationContextInitializer{ @Override public void initialize(ConfigurableApplicationContext applicationContext) { System.out.println("-----MyApplicationContextInitializer initialize-----"); } }
除了使用Order注解,还可以采用实现Ordered接口的方式,排序验证结果都是一样的。
通过源码分析ApplicationContextInitializer何时被调用
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { return run(new Class[]{primarySource}, args); } public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) { return (new SpringApplication(primarySources)).run(args); } public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); this.configureHeadlessProperty(); SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.starting(); Collection exceptionReporters; try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); this.configureIgnoreBeanInfo(environment); Banner printedBanner = this.printBanner(environment); context = this.createApplicationContext(); exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); // this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); this.refreshContext(context); this.afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } listeners.started(context); this.callRunners(context, applicationArguments); } catch (Throwable var10) { this.handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); } try { listeners.running(context); return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } }
在SpringBoot 2.3.6.RELEASE版本中,在this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);方法中调用。
ApplicationRunner or CommandLineRunner
应用服务启动时,加载一些数据和执行一些应用的初始化动作。如:删除临时文件,清除缓存信息,读取配置文件信息,数据库连接等。
SpringBoot提供了CommandLineRunner和ApplicationRunner接口。当接口有多个实现类时,提供了@order注解实现自定义执行顺序,也可以实现Ordered接口来自定义顺序。
注意:数字越小,优先级越高,也就是@Order(1)注解的类会在@Order(2)注解的类之前执行。
两者的区别在于:
ApplicationRunner中run方法的参数为ApplicationArguments,而CommandLineRunner接口中run方法的参数为String数组。想要更详细地获取命令行参数,那就使用ApplicationRunner接口。
ApplicationRunner
@Component @Order(value = 10) public class AgentApplicationRun2 implements ApplicationRunner { @Override public void run(ApplicationArguments applicationArguments) throws Exception { } }
CommandLineRunner
@Component @Order(value = 11) public class AgentApplicationRun implements CommandLineRunner { @Override public void run(String... strings) throws Exception { } }
接口不同于:
ApplicationRunner中run方法的参数为ApplicationArguments,而CommandLineRunner接口中run方法的参数为String数组。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决