SpringBoot初始化接口CommandLineRunner示例详解
作者:多冷啊、我在东北玩泥巴
CommandLineRunner的使用
接口定义
Spring官方给出的接口定义
package org.springframework.boot; @FunctionalInterface public interface CommandLineRunner { void run(String... args) throws Exception; }
在 Spring Boot 应用程序中,CommandLineRunner 是一个接口,用于定义在应用程序启动后执行的任务。它有一个单独的方法 run(),在应用程序启动完成后自动调用。
具体来说,CommandLineRunner 的 run() 方法会在 Spring Boot 应用程序完成启动过程后立即执行。这意味着在 Spring 上下文加载完毕、所有 Bean 实例化完成之后,run() 方法将被调用。可以看到,该接口还是一个函数式接口,函数式的方式就不演示了,我们这里继承该接口实现方法即可
使用
在我们需要进行初始化的类中直接实现该接口的 run()
方法即可注意:如果你要run方法能被执行,你必须将实现了该接口的类注入到Spring容器中
CommandLineRunner 接口通常用于在应用程序启动后执行一些初始化任务或准备工作,例如加载初始数据、设置定时任务、启动后台线程等。通过实现 CommandLineRunner 接口并覆盖 run() 方法,你可以将你的任务逻辑放在其中,以便在应用程序启动时自动执行。
@Component public class MyComponent implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("MyComponent -> CommandLineRunner"); } }
执行结果
可以看到该方法在Application started之后才执行
执行顺序
需要注意的是,如果应用程序中有多个实现了 CommandLineRunner 的类,它们的执行顺序可能是不确定的。如果你需要确保执行顺序,可以使用 @Order 注解或实现 org.springframework.core.Ordered 接口来指定顺序。在 Spring Framework 中,@Order 注解用于指定组件的执行顺序。它可以应用于类级别或方法级别。
使用 @Order 注解
示例代码如下所示:
定义两个类,order分别为1和2
@Component public class MyComponent1 implements CommandLineRunner { Logger logger = LoggerFactory.getLogger(MyComponent1.class); @Order(1) @Override public void run(String... args) throws Exception { logger.info("MyComponent1 -> CommandLineRunner"); } }
@Component public class MyComponent2 implements CommandLineRunner { Logger logger = LoggerFactory.getLogger(MyComponent2.class); @Order(2) @Override public void run(String... args) throws Exception { logger.info("MyComponent2 -> CommandLineRunner"); } }
运行结果:
对于类级别的 @Order 注解,它指定了组件在 Spring 上下文中的加载顺序。具体来说,数值越小的组件将先被加载和初始化。如果没有显式指定 @Order 注解,默认情况下,组件的加载顺序是不确定的。
实现Orderd接口
实现org.springframework.core.Ordered 中的getOrder()方法
下面再创建两个类,并实现 org.springframework.core.Ordered 接口。
@Component public class MyComponent3 implements Ordered, CommandLineRunner { Logger logger = LoggerFactory.getLogger(MyComponent3.class); @Override public void run(String... args) throws Exception { logger.info("MyComponent3 -> CommandLineRunner"); } @Override public int getOrder() { return 3; } }
@Component public class MyComponent4 implements Ordered, CommandLineRunner { Logger logger = LoggerFactory.getLogger(MyComponent4.class); @Override public void run(String... args) throws Exception { logger.info("MyComponent4 -> CommandLineRunner"); } @Override public int getOrder() { return 4; } }
执行结果如下:
可以看到无论使用哪种方式都是order值更小的优先执行,但是实现org.springframework.core.Ordered接口的会比在方法上使用@Order注解的有更高的优先级,所有实现org.springframework.core.Ordered接口的类中的run方法会都会优先于在方法上使用@Order注解执行,无论设置的值是否比注解中的更小
我这里猜测可能是实现接口是类级别的order,所以会优先于方法级别的order,所以我又做了下面实验,将MyComponent1和MyComponent2中的@Order注解挪到类声明上,所以就变成了下面这样
@Order(1) @Component public class MyComponent1 implements CommandLineRunner { Logger logger = LoggerFactory.getLogger(MyComponent1.class); @Override public void run(String... args) throws Exception { logger.info("MyComponent1 -> CommandLineRunner"); } }
@Order(2) @Component public class MyComponent2 implements CommandLineRunner { Logger logger = LoggerFactory.getLogger(MyComponent2.class); @Override public void run(String... args) throws Exception { logger.info("MyComponent2 -> CommandLineRunner"); } }
再次执行结果:
果然MyComponent1和MyComponent2排到前面去了,看来猜测没有错
排序总结
- @Order注解在类上会比注解在方法上拥有更高的优先级
- 实现org.springframework.core.Ordered接口的getOrder()方法和@Order注解在类上是相同的优先级
- order值越小越先执行
- order值可以为负数,一样遵循越小越优先的规则
到此这篇关于SpringBoot初始化接口CommandLineRunner的文章就介绍到这了,更多相关SpringBoot初始化接口CommandLineRunner内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!