首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

SpringBoot 启动时初始化数据

0x01:前言

在使用 springboot 搭建项目的时候,有时候会碰到在项目启动时初始化一些操作的需求,针对这种需求 springboot(spring) 提供了以下几种方案:

ApplicationRunner 与 CommandLineRunner 接口

Spring Bean 初始化的I nitializingBean, init-method 和 PostConstruct

Spring 的事件机制

0x02:ApplicationRunner与CommandLineRunner

如果需要在SpringApplication启动时执行一些特殊的代码,可以实现ApplicationRunner 或 CommandLineRunner 接口,这两个接口工作方式相同,都只提供单一的 run() 方法,而且该方法仅在SpringApplication.run(…)完成之前调用,更准确的说是在构造 SpringApplication 实例完成之后调用 run() 的时候,具体分析见后文,所以这里将他们分为一类。

ApplicationRunner

构造一个类实现ApplicationRunner接口

CommandLineRunner

对于这两个接口而言,可以通过 Order 注解或者使用 Ordered 接口来指定调用顺序,@Order() 中的值越小,优先级越高

当然也可以同时使用 ApplicationRunner 和 CommandLineRunner,默认情况下前者比后者先执行,但是这没有必要,使用一个就可以了。

两者的联系与区别

这两个接口都有 run() 方法,只不过它们的参数不一样,CommandLineRunne r的参数是最原始的参数,没有进行任何处理,ApplicationRunner 的参数是ApplicationArguments, 是对原始参数的进一步封装。

简要跟踪一下源码看 ApplicationRunner(CommandLineRunner) 是如何被调用的。

Springboot 在启动的时候,都会构造一个 SpringApplication 实例,至于这个实例怎么构造的,这里不去探究了,有感兴趣的可以去看下源码。这里主要看ApplicationRunner 是如何被调用的,而它的调用就是在SpringApplication这个实例调用run方法中。

进入run方法

执行 SpringApplication 的 run 方法

一路点击 run() 来,发现对 ApplicationRunner 的调用实际上在 callRunners 方法中

对于 CommandLineRunner 或者 ApplicationRunner 来说,需要注意的两点:

所有 CommandLineRunner / ApplicationRunner 的执行时点是在 SpringBoot 应用的 ApplicationContext 完全初始化开始工作之后,callRunners() 可以看出是 run 方法内部最后一个调用的方法(可以认为是main方法执行完成之前最后一步)

只要存在于当前 SpringBoot 应用的 ApplicationContext 中的任何CommandLineRunner / ApplicationRunner,都会被加载执行(不管你是手动注册还是自动扫描去Ioc容器)

0x03:Spring Bean初始化的InitializingBean,init-method和PostConstruct

InitializingBean接口

InitializingBean 接口为 bean 提供了初始化方法的方式,它只包括 afterPropertiesSet()方法。

在 spring 初始化 bean 的时候,如果bean实现了 InitializingBean 接口,在对象的所有属性被初始化后之后才会调用 afterPropertiesSet() 方法

当然,可以看出spring初始化bean肯定会在 ApplicationRunner 和 CommandLineRunner 接口调用之前。

当然有一点要注意的是,尽管使用 InitialingBean 接口可以实现初始化动作,但是官方并不建议使用 InitializingBean 接口,因为它将你的代码耦合在Spring代码中,官方的建议是在 bean 的配置文件指定 init-method 方法,或者在 @Bean 中设置 init-method 属性

init-method和@PostConstruct

前面就说过官方文档上不建议使用 InitializingBean 接口,但是我们可以在 元素的 init-method 属性指定 bean 初始化之后的操作方法,或者在指定方法上加上 @PostConstruct 注解来制定该方法在初始化之后调用

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20210918A0FES000?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

相关快讯

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券