如何实现springboot容器加载完后立即执行的方法
简单使用场景:
在我们启动项目时,经常有动态初始化的数据。
可能有人说:那我可以写在构造方法之中初始化数据呀?
这样当然可以,但是会存在以下几个问题:
- 当前类中所依赖注入的Bean过多时,手动去创建带参构造方法会让代码显得臃肿且不优雅,同时面临着,每次新增一个bean时,需要进一步手动修改带参构造方法,且执行过程处于,bean的初始化阶段。这样只能静态的初始化一些数据,想要通过服务去动态的调用一些数据只能说是歇逼了,不能说没有办法但是非常的麻烦,远没有利用已经写好的注册进入spring容器的component调用方便,且不同的类中假如有同样初始化逻辑就需要写臃肿的代码进行同样
- 我想执行某一些复杂代码块操作,或者想调用其他的服务这些数据可能是从数据库来,也可能通过别的服务调用而来,作用于当前类,不同于固定的数据写在静态的static代码块和构造方法中初始化。动态的数据获取需要调用服务来完成,这样写在static中会存在容器未加载完成导致启动顺序的问题,从而引发NPE。
- … …
那么有没有,有没有什么方法去解决这个问题呢?
当然是有,其实这就是一个springboot容器启动顺序的问题
1、如何实现springboot容器加载完后执行的方法
在Spring Boot中,您可以使用ApplicationRunner
或 CommandLineRunner
接口来实现此目的。
ApplicationRunner 和 CommandLineRunner接口都提供了一个 run() 方法,该方法在Spring Boot应用程序启动后立即执行。您可以在这个方法中执行任何逻辑,例如初始化数据、启动后台任务等。
以下是一个示例 ApplicationRunner 实现:
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// do something after application started
}
}
在这个例子中,我们定义了一个名为MyApplicationRunner的组件,并实现了ApplicationRunner接口。在 run() 方法中,我们可以执行任何逻辑,例如初始化数据、启动后台任务等。
请注意,您需要将MyApplicationRunner组件标记为@Component,以便Spring Boot可以自动检测和加载它。
如果您想要更细粒度的控制,您可以使用 @Order 注解来指定ApplicationRunner或CommandLineRunner的执行顺序。例如:
@Component
@Order(1)
public class MyFirstApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// do something first
}
}
@Component
@Order(2)
public class MySecondApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// do something second
}
}
在这个例子中,我们定义了两个ApplicationRunner组件,并使用@Order注解来指定它们的执行顺序。
MyFirstApplicationRunner将在MySecondApplicationRunner之前执行。
请注意,@Order注解的值越小,优先级越高。
1.1、ApplicationRunner和CommandLineRunner接口有什么不同?
这两个接口都可以在Spring Boot应用程序启动后执行逻辑,但它们之间有一些区别。ApplicationRunner接口提供了一个run()方法,该方法接受一个ApplicationArguments
对象作为参数。ApplicationArguments对象包含应用程序启动时传递的命令行参数。您可以使用ApplicationArguments对象来访问这些参数,并在run()方法中执行任何逻辑。
CommandLineRunner接口也提供了一个run()方法,但它接受一个String数组
作为参数,该数组包含应用程序启动时传递的命令行参数。您可以使用String数组来访问这些参数,并在run()方法中执行任何逻辑。
因此,ApplicationRunner和CommandLineRunner接口之间的主要区别在于:
它们接受的参数类型不同。如果您需要访问应用程序启动时传递的命令行参数,您应该使用ApplicationRunner接口。如果您只需要访问命令行参数的字符串数组,您可以使用CommandLineRunner接口。