首页 > 其他分享 >CommandLineRunner、ApplicationRunner、InitializingBean、@PostConstruct 执行顺序

CommandLineRunner、ApplicationRunner、InitializingBean、@PostConstruct 执行顺序

时间:2023-07-28 11:02:16浏览次数:48  
标签:InitializingBean CommandLineRunner run PostConstruct 接口 ApplicationRunner public

概述

开发中可能会有这样的场景,需要在容器启动的时候执行一些内容。比如读取配置文件,数据库连接之类的。SpringBoot给我们提供了两个接口来帮助我们实现这种需求,两个启动加载接口分别是:CommandLineRunner和ApplicationRunner。Spring 提供了接口 InitializingBean,jdk提供了@PostConstruct.

CommandLineRunner和ApplicationRunner区别

CommandLineRunner和ApplicationRunner的作用是相同的。不同之处在于CommandLineRunner接口的run()方法接收String数组作为参数,即是最原始的参数,没有做任何处理;而ApplicationRunner接口的run()方法接收ApplicationArguments对象作为参数,是对原始参数做了进一步的封装。

当程序启动时,我们传给main()方法的参数可以被实现CommandLineRunner和ApplicationRunner接口的类的run()方法访问,即可接收启动服务时传过来的参数。我们可以创建多个实现CommandLineRunner和ApplicationRunner接口的类。为了使他们按一定顺序执行,可以使用@Order注解或实现Ordered接口。

ApplicationRunner接口的示例

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
@Order(value = 1)
public class JDDRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {

        System.out.println("这个是测试ApplicationRunner接口");
               String strArgs = Arrays.stream(arg0.getSourceArgs()).collect(Collectors.joining("|"));
        System.out.println("Application started with arguments:" + strArgs);
    }
}

启动时候指定参数:java -jar xxxx.jar data1 data2 data3。
运行结果:
这个是测试ApplicationRunner接口
Application started with arguments:data1|data2|data3

CommandLineRunner接口示例

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class TestCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("这个是测试CommandLineRunn接口");
         String strArgs = Arrays.stream(args).collect(Collectors.joining("|"));
        System.out.println("Application started with arguments:" + strArgs);
    }
}

启动时候指定参数:java -jar xxxx.jar data1 data2 data3。 运行结果: 这个是测试CommandLineRunn接口 Application started with arguments:data1|data2|data3

CommandLineRunner和ApplicationRunner的执行顺序

在spring boot程序中,我们可以使用不止一个实现CommandLineRunner和ApplicationRunner的bean。为了有序执行这些bean的run()方法,可以使用@Order注解或Ordered接口。

@Component
@Order(2)
public class ApplicationRunnerBean1 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments arg0) throws Exception {
        System.out.println("ApplicationRunnerBean 1");
    }
}

@Component
@Order(4)
public class ApplicationRunnerBean2 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments arg0) throws Exception {
        System.out.println("ApplicationRunnerBean 2");
    }
}

@Component
@Order(1)
public class CommandLineRunnerBean1 implements CommandLineRunner {
    @Override
    public void run(String... args) {
        System.out.println("CommandLineRunnerBean 1");
    }
}

@Component
@Order(3)
public class CommandLineRunnerBean2 implements CommandLineRunner {
    @Override
    public void run(String... args) {
        System.out.println("CommandLineRunnerBean 2");
    }
}

执行结果:
CommandLineRunnerBean 1 ApplicationRunnerBean 1 CommandLineRunnerBean 2 ApplicationRunnerBean 2

  另外,通过分析springboot启动的源码可以发现,在applicationContext容器加载完成之后,会调用SpringApplication类的callRunners方法:该方法中会获取所有实现了ApplicationRunner和CommandLineRunner的接口bean,然后依次执行对应的run方法,并且是在同一个线程中执行。因此如果有某个实现了ApplicationRunner接口的bean的run方法一直循环不返回的话,后续的代码将不会被执行。

ApplicationRunner、InitializingBean、@PostConstruct执行顺序问题

InitializingBean接口的用法

InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候都会执行该方法。注意,实现该接口的最好加上Spring的注解注入,比如@Component。

@PostConstruct注解的用法

如果想在生成对象时候完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么就无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。 优先级: Constructor >> @Autowired >> @PostConstruct。

@Component
public class Test implements InitializingBean, ApplicationRunner, CommandLineRunner {

    @PostConstruct
    public void init(){
        System.out.println("PostConstruct 方法执行");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean 方法执行");
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("这个是测试ApplicationRunner接口");

    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println("这个是测试CommandLineRunn接口");
    }
}

运行结果:
PostConstruct 方法执行 InitializingBean 方法执行
这个是测试ApplicationRunner接口 这个是测试CommandLineRunn接口

由此可知: @PostConstruct>InitializingBean>ApplicationRunner>CommandLineRunner,当然如果涉及到类中的static代码块,则是:
static>@PostConstruct>InitializingBean>ApplicationRunner>CommandLineRunner

————————————————
原文链接:https://blog.csdn.net/w3634839644/article/details/126035000

标签:InitializingBean,CommandLineRunner,run,PostConstruct,接口,ApplicationRunner,public
From: https://www.cnblogs.com/blogtech/p/17587011.html

相关文章

  • spring注解之@PostConstruct在项目启动时执行指定方法
    学习资料:https://juejin.cn/post/7247543825534419000https://qa.1r1g.com/sf/ask/238458881/......
  • Spring核心接口之InitializingBean
    一、InitializingBean接口说明InitializingBean接口为bean提供了属性初始化后的处理方法,它只包括afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。packageorg.springframework.beans.factory;/***Interfacetobeimplementedbybeanstha......
  • Spring核心接口之InitializingBean
    一、InitializingBean接口说明InitializingBean接口为bean提供了属性初始化后的处理方法,它只包括afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。packageorg.springframework.beans.factory;/***Interfacetob......
  • SpringBoot项目预加载数据——ApplicationRunner、CommandLineRunner、InitializingBe
    0、参考、业务需求参考:https://www.cnblogs.com/java-chen-hao/p/11835120.html#_label1https://zhuanlan.zhihu.com/p/541268993业务需求:缓存数据字典数据、初始化线程池、提前加载好加密证书1、方式实现ApplicationRunner接口实现CommandLineRunner接口实现In......
  • @PostConstruct的顺序
    其实从依赖注入的字面意思就可以知道,要将对象p注入到对象a,那么首先就必须得生成对象p与对象a,才能执行注入。所以,如果一个类A中有个成员变量p被@Autowired注解,那么@Autowired注入是发生在A的构造方法执行完之后的。如果想在生成对象时候完成某些初始化操作,而偏偏这些初始化操作又......
  • 【ⓈSpring & Spring MVC】Spring核心接口InitializingBean与SmartInitializingSingle
    SmartInitializingSingletonSmartInitializingSingleton中只有一个接口afterSingletonsInstantiated(),其作用是在spring容器管理的所有单例对象(非懒加载对象)初始化完成之后调用的回调接口。InitializingBeanInitializingBean接口为bean提供了初始化方法的方式,它只包括afterProp......
  • Java SpringBoot Bean InitializingBean
    Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean。工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂Bean的getObject方法所返回的对象。Spring初始化bean有两种方式:实现InitializingBean接口,实现afterPropertiesSet方法。(比通过反射......
  • Java SpringBoot Bean InitializingBean
    Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean。工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂Bean的getObject方法所返回的对象。Spring初始化bean有两种方式:实现InitializingBean接口,实现afterPropertiesSet方法。(比通过......
  • 【Spring原理分析-Aware接口&InitializingBean&初始化与销毁执行顺序】
    一、Aware接口&InitializingBean1、基础准备2、总结3、补充:EmbeddedValueResolverAware二、@Autowired和@PostConstruct注解失效1、基础准备2、失效情形3、失效原因4、使用Aware接口避免失效5、总结补充总结一、Aware接口&InitializingBean1、基础准备①编写MyBean实......
  • Spring Boot 中的 ApplicationRunner 和 CommandLineRunner
    前言一般项目中的初始化操作,初次遇见,妙不可言。如果你还有哪些方式可用于初始化操作,欢迎在评论中分享出来~ApplicationRunner和CommandLineRunnerSpringBoot应用,在......