启动后,执行的任务,

方法一:通过ApplicationRunner或者CommandLineRunner的run方法完成

@Component
public class RunnerTest implements ApplicationRunner, CommandLineRunner {
 
  @Override
  public void run(ApplicationArguments args) throws Exception {
    System.out.println("ApplicationRunner 启动任务");
  }
 
  @Override
  public void run(String... args) throws Exception {
    System.out.println("CommandLineRunner 启动任务");
    }
  }
}

方法二:通过ApplicationListener完成

@Service
public class TestService implements  ApplicationListener<ContextRefreshedEvent> {

	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		// TODO Auto-generated method stub
		if (event.getApplicationContext().getParent() == null) {//保证只执行一次
	           //需要执行的方法
			System.out.println("========ApplicationListener  执行任务========");
	       }
	}
}

方法三:通过注解实现

    @PostConstruct
	public void init1() {
		System.out.println("@PostConstruct 启动任务");
	}

我在springboot的main方法加了启动完成的输出

@SpringBootApplication
public class TestApplication{

	public static void main(String[] args) {
		SpringApplication application = new SpringApplication(MonitorForDbApplication.class);
		ConfigurableApplicationContext context = application.run(args);
        ApplicationContextUtil.setApplicationContext(context);
        System.out.println("启动完成");
	}

这几种及执行的顺序如下:所有的任务执行完成后,启动才真正结束

2022-08-19 17:15:40.467  INFO 24016 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
@PostConstruct 启动任务
2022-08-19 17:15:41.314  WARN 24016 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2022-08-19 17:15:41.669  INFO 24016 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 10061 (http) with context path ''
========ApplicationListener  执行任务========
2022-08-19 17:15:41.686  INFO 24016 --- [           main] c.f.m.MonitorForDbApplication            : Started MonitorForDbApplication in 4.614 seconds (JVM running for 5.114)
ApplicationRunner 启动任务
CommandLineRunner 启动任务

启动完成

显然通过ApplicationRunner或者CommandLineRunner实现是都程序都加载完成后执行的,不影响访问,不通担心注入@Autowired的问题。但是还是有问题,如果我在里面直接抛出异常,会影响程序的启动,直接shundown。

@Override
	public void run(String... args) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("CommandLineRunner 启动任务");
		throw new RuntimeException();
2022-08-19 17:30:05.536 ERROR 15784 --- [           main] o.s.boot.SpringApplication               : Application run failed

java.lang.IllegalStateException: Failed to execute CommandLineRunner
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:785) ~[spring-boot-2.6.10.jar:2.6.10]
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:766) ~[spring-boot-2.6.10.jar:2.6.10]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) ~[spring-boot-2.6.10.jar:2.6.10]
	at com.fdway.monitorForDB.MonitorForDbApplication.main(MonitorForDbApplication.java:22) [classes/:na]
Caused by: java.lang.RuntimeException: null
	at com.fdway.monitorForDB.ScheduledService.run(ScheduledService.java:57) ~[classes/:na]
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:782) ~[spring-boot-2.6.10.jar:2.6.10]
	... 3 common frames omitted

2022-08-19 17:30:05.657  INFO 15784 --- [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-08-19 17:30:05.659  INFO 15784 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2022-08-19 17:30:05.666  INFO 15784 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

说明启动CommandLineRunner的执行其实是整个应用启动的一部分,此时CommandLineRunner的run方法执行时抛出异常,直接影响主程序的启动。


解决办法:

    这样的问题该如何解决呢?这个操作影响了主线程,那么我们是否可以重新开启一个线程,让他单独去做我们想要做的操作呢。

    @Override
	public void run(String... args) throws Exception {
		// TODO Auto-generated method stub
		
        new Thread(){
            public void run() {
            	System.out.println("CommandLineRunner 启动任务");
                throw new RuntimeException();
            }
        }.start();
        
	}
2022-08-19 17:36:28.404  INFO 21428 --- [           main] c.f.m.MonitorForDbApplication            : Started MonitorForDbApplication in 4.644 seconds (JVM running for 5.133)
CommandLineRunner 启动任务
启动完成
Exception in thread "Thread-2" java.lang.RuntimeException
	at com.fdway.monitorForDB.ScheduledService$1.run(ScheduledService.java:60)

这样既解决了报错影响程序的问题,又解决了程序启动过慢的问题。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐