Spring启动前后自动执行代码
有些Spring项目在启动的时候需要预加载一些资源,有以下方式:
一、启动前执行
1、Java类加载阶段
①:static变量
在类加载的准备阶段为static变量分配内存并设置类初始值(数据字段类型的默认值)
在类加载的初始化阶段为static变量赋定义的值
②:static代码块
在类加载的初始化阶段执行静态代码块
2、监听器
自定义监听器实现ApplicationListener接口,监听以下事件
容器开始启动 | ApplicationStartingEvent |
二、启动中执行
1、bean实例化阶段
①:构造代码块
每次创建对象时执行一次,优先于构造方法执行
②:构造方法
每次创建对象时执行一次
2、Spring bean初始化阶段
①:如果bean实现了BeanNameAware接口,Spring将调用setBeanName()方法将bean的ID传递入
②:如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
③:如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传进来
④:@PostConstruct 标注的方法,在执行完构造器之后初始化对象时执行
⑤:afterPropertiesSet方法,若bean实现了InitializingBean接口,接着执行此初始化方法
⑥:initMethod,@Bean注解上自定义的初始化方法
3、Spring监听器
自定义监听器实现ApplicationListener接口,监听以下事件
在环境(environment)准备完成,容器创建之前 | ApplicationEnvironmentPreparedEvent |
容器创建完成,并且准备完成,资源加载之前 | ApplicationContextInitializedEvent |
容器加载完成,刷新之前 | ApplicationPreparedEvent |
三、启动后执行
1、Spring监听器
自定义监听器实现ApplicationListener接口,监听以下事件
容器启动完成 | ApplicationStartedEvent |
容器运行 | ApplicationReadyEvent |
容器启动失败 | ApplicationFailedEvent |
2、CommandLineRunner 和 ApplicationRunner
两个接口都是在ApplicationStartedEvent事件之后执行 ,用于在Spring容器启动完成后执行一些功能。
对应下图,callRunners方法:
先执行 ApplicationRunner 后执行 CommandLineRunner
两个接口都有一个run方法,区别在于run方法的入参不同
CommandLineRunner | void run(String... args) throws Exception; |
ApplicationRunner | void run(ApplicationArguments args) throws Exception; |
①:CommandLineRunner,接口,用于指示当一个bean被包含在一个SpringApplication中时应该运行它。可以在同一个应用程序上下文中定义多个CommandLineRunner bean,并且可以使用ordered接口或@Order注释进行排序
②:ApplicationRunner,接口,用于指示当一个bean被包含在一个SpringApplication中时应该运行它。可以在同一个应用程序上下文中定义多个ApplicationRunner bean,并且可以使用ordered接口或@Order注释进行排序
使用:自定义类实现CommandLineRunner或ApplicationRunner接口,在实现的run()方法里执行想要自动执行的代码。
Order注解:
当有多个类实现了CommandLineRunner和ApplicationRunner接口时,可以通过在类上添加@Order注解来设定运行顺序。
示例:
SpringApplicationStartedListener:
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* 监听当容器启动后,做一些数据预热工作
*/
@Component
public class SpringApplicationStartedListener implements ApplicationListener<ApplicationStartedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
// 加载数据到缓存 ...
}
}
CacheRunner:
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 容器启动后预热缓存
*/
@Component
public class CacheRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// 预热缓存...
}
}
END.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类