本文介绍SpringBoot项目的四种启动后执行功能的方式。
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Order(value = 2) public class ApplicationRunnerTest implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("========ApplicationRunner========"); // 失败后,服务停止 // throw new RuntimeException(); } }
类需要实现ApplicationRunner接口,实现public void run(ApplicationArguments args) throws Exception 方法
类增加@Component注解成为spring可管理的bean
多个ApplicationRunner实现类,可以通过@Order注解指定执行顺序,数越小就越先执行
当run方法执行异常,则服务启动失败
import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Order(value = 2) public class CommandLineRunnerTest implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("========CommandLineRunner========"); // 失败后,服务停止 // throw new RuntimeException(); } }
类需要实现CommandLineRunner接口,实现public void run(String... args) throws Exception 方法
类增加@Component注解成为spring可管理的bean
多个CommandLineRunner实现类,可以通过@Order注解指定执行顺序,数越小就越先执行
当run方法执行异常,则服务启动失败
import javax.annotation.PostConstruct; import org.springframework.stereotype.Component; @Component public class PostConstructTest { @PostConstruct public void init() { System.out.println("========PostConstruct========"); // 失败后,服务停止 // throw new RuntimeException(); } }
类增加@Component注解成为spring可管理的bean
在需要执行的方法上,增加@PostConstruct注解,方法名称不一定是init
当方法执行异常,则服务启动失败
多个方法标注@Component注解,按照顺序依次执行,即使方法上标注@Order注解。
import javax.annotation.PostConstruct; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component public class PostConstructTest { @PostConstruct @Order(value = 2) public void init() { System.out.println("========PostConstruct========"); } @PostConstruct @Order(value = 1) public void init2() { System.out.println("========PostConstruct2========"); } }
虽然将两个方法上都加了@Order注解,并且init2()方法的设置顺序小于init()方法,但是仍然先执行init()方法
import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Component; @Component public class ApplicationListenerTest implements ApplicationListener{ @Override public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("========ApplicationListener========"); // 失败后,服务停止 // throw new RuntimeException(); } }
类需要实现ApplicationListener接口,实现public void onApplicationEvent(E event) 方法
类增加@Component注解成为spring可管理的bean
多个CommandLineRunner实现类,可以通过@Order注解指定执行顺序,数越小就越先执行
当onApplicationEvent方法执行异常,则服务启动失败
当onApplicationEvent方法采用异步执行时,方法执行异常,服务启动不会失败
@PostConstruct注解在类被加载的时候执行,而ApplicationRunner、CommandLineRunner接口是在工程启动后才执行
ApplicationListener接口执行顺序晚于@PostConstruct注解,早于ApplicationRunner、CommandLineRunner接口
四种方式在执行方法时,只要失败,服务均不能启动
ApplicationRunner、CommandLineRunner接口同时存在时,通过指定@Order注解可以改变总体的自行顺序,并不是哪个接口一定先执行
无@Order注解或者@Order注解的顺序一致时,ApplicationRunner、CommandLineRunner接口同时存在时,则ApplicationRunner接口优先执行
注 由于ApplicationListener接口是基于发布订阅模式的,因此可以支持异步执行,异步执行时,ApplicationListener接口早于ApplicationRunner、CommandLineRunner接口执行,但不是等到ApplicationListener接口执行完成后才执行ApplicationRunner、CommandLineRunner接口
import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.core.annotation.Order; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @Component public class ApplicationListenerTest implements ApplicationListener{ @Override @Async // 已经在SpringBoot启动类增加了@EnableAsync注解 public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("========ApplicationListener========"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } // 由于异步执行,所以方法执行失败后,仍然不会停止服务 // throw new RuntimeException(); } }
对于@Order注解,也可以采用Ordered接口来实现,需要实现public int getOrder()方法
@Component //@Order(value = 2) public class CommandLineRunnerTest implements CommandLineRunner ,Ordered { @Override public int getOrder() { return 1; } @Override public void run(String... args) throws Exception { System.out.println("========CommandLineRunner========"); // 失败后,服务停止 // throw new RuntimeException(); } }
ApplicationListener 扩展方式
由于ApplicationListener 是发布订阅模式,可以直接采用@EventListener注解来实现。
import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; @Component public class EventListenerTest { @EventListener public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("========EventListener========"); // 失败后,服务停止 // throw new RuntimeException(); } }