Spring启动时实现初始化有哪些方式?

 更新时间:2021年06月09日 17:24:05   作者:pbxs  
今天给大家带来的文章是关于Spring的相关知识,文章围绕着Spring启动时实现初始化有哪些方式展开,文中有非常详细的介绍,需要的朋友可以参考下

一、Spring启动时实现初始化的几种方式

准确的说是spring容器实例化完成后,几种初始化的方式。为什么这么说呢?下看面示例:

@Slf4j
@Component
public class InitBeanDemo {
    @Autowired
    private Environment env;

    public InitBeanDemo() {
        log.info("DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
        log.info("ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
    }

示例是在bean的构造方法里做一些初始化的工作,示例比较简单只做了日志打印。是理想很丰满,现实很骨感,报错了:Constructor threw exception; nested exception is java.lang.NullPointerException。
原因是,Environment尚未初始化完成。

接下来我们来探索一下 有哪些初始化方式能满足上面示例的需求。

二、构造方法里初始化

可以正常运行,在所有初始化方式里执行时机最早。原理是在InitBeanDemo实例化前就实例化了Environment。

@Component
public class InitBeanDemo {

    private final Environment env;

    @Autowired
    public InitBeanDemo (Environment environment) {
        this.env = environment;
        log.info("Constructor DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
        log.info("Constructor ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
    }
}

三、常规三件套

常规三件套:@PostConstruct、InitializingBean、initMethod。 如果你愿意的话,三种方式可以在同一个Bean下同时使用,执行的优先级@PostConstruct > InitializingBean > initMethod。

@PostConstruct注解

在一个可以被扫描到Bean里,添加一个public void xxx()方法并加上@PostConstruct注解,方法里编写需要初始化的逻辑。
同一个应用程序里可以有多个@PostConstruct注解,同一个Bean里也可以有多个@PostConstruct注解。

@Slf4j
@Component
public class InitBeanDemo {
    @Autowired
    private Environment env;

    @PostConstruct
    public void init() {
        log.info("@PostConstruct DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
        log.info("@PostConstruct ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
    }

实现InitializingBean接口

实现InitializingBean接口,在afterPropertiesSet() 方法里编写需要初始化的逻辑。
同一个应用程序里可以有多个实现InitializingBean接口的类,执行时机会按类名的自然顺序排序。

@Slf4j
@Component
public class InitBeanDemo implements InitializingBean {
    @Autowired
    private Environment env;

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("InitializingBean DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
        log.info("InitializingBean ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
    }
}

指定Bean的initMethod方法

使用@Bean注解的initMethod属性可用于Bean的初始化后执行的方法。initMethod必须是public void 的无参构造方法。

@Slf4j
public class InitBeanDemo implements InitializingBean {
    @Autowired
    private Environment env;
    
	public void initMethod() {
        log.info("initMethod DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
        log.info("initMethod ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
    }
@Configuration
public class InitBeanConfig {

    @Bean(initMethod="initMethod")
    public InitBeanDemo initBeanDemo () {
        return new InitBeanDemo();
    }

}

等同于 在XML 配置中的init-method属性:

<bean id="initBeanDemo" class="com.xxx.InitBeanDemo" init-method="initMethod"></bean>

四、自定义ApplicationListener监听

两种方式,一种实现接口,另一种使用注解。

实现ApplicationListener接口

监听ContextRefreshedEvent事件。

@Slf4j
@Component
public class InitBeanDemo implements ApplicationListener<ContextRefreshedEvent>{
    @Autowired
    private Environment env;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        log.info("ApplicationListener DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
        log.info("ApplicationListener ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
    }
}

@EventListener注释

方法参数里指定ContextRefreshedEvent事件。

@Slf4j
@Component
public class InitBeanDemo {
    @Autowired
    private Environment env;

    @EventListener
    public void onApplicationEvent2(ContextRefreshedEvent event) {
        log.info("@EventListener DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
        log.info("@EventListener ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
    }
}

五、Spring Boot提供的初始化接口

 ApplicationRunner接口

@Slf4j
@Component
public class InitBeanDemo implements ApplicationRunner {
    @Autowired
    private Environment env;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("ApplicationRunner: {}", args);
        log.info("ApplicationRunner: {}", args.getOptionNames());
        log.info("ApplicationRunner DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
        log.info("ApplicationRunner ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
    }
}

CommandLineRunner接口

可以在同一个应用程序上下文中定义多个CommandLineRunner bean,并且可以使用@Ordered接口或@Order注释进行排序。

@Slf4j
@Component
public class InitBeanDemo implements CommandLineRunner {
    @Autowired
    private Environment env;

    @Override
    public void run(String... args) throws Exception {
        log.info("CommandLineRunner: {}", args);
        log.info("CommandLineRunner DefaultProfiles: {}", Arrays.asList(env.getDefaultProfiles()));
        log.info("CommandLineRunner ActiveProfiles: {}", Arrays.asList(env.getActiveProfiles()));
    }
}

在同一个Bean里使用以上初始化方式的执行先后顺序

在同一个Bean里使用以上初始化方式,运行的日志片段:

2021-06-07 11:24:41|INFO |main|c.c.s.s.t.ConstructorInitDemo|Constructor DefaultProfiles: [default]
2021-06-07 11:24:41|INFO |main|c.c.s.s.t.ConstructorInitDemo|Constructor ActiveProfiles: [sit]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|@PostConstruct DefaultProfiles: [default]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|@PostConstruct ActiveProfiles: [sit]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|InitializingBean DefaultProfiles: [default]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|InitializingBean ActiveProfiles: [sit]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|initMethod DefaultProfiles: [default]
2021-06-07 11:24:42|INFO |main|c.c.s.s.test.InitBeanDemo|initMethod ActiveProfiles: [sit]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|@EventListener DefaultProfiles: [default]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|@EventListener ActiveProfiles: [sit]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationListener DefaultProfiles: [default]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationListener ActiveProfiles: [sit]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationRunner: org.springframework.boot.DefaultApplicationArguments@68bef3df
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationRunner: []
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationRunner DefaultProfiles: [default]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|ApplicationRunner ActiveProfiles: [sit]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|CommandLineRunner: {}
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|CommandLineRunner DefaultProfiles: [default]
2021-06-07 11:24:44|INFO |main|c.c.s.s.test.InitBeanDemo|CommandLineRunner ActiveProfiles: [sit]

也即 整篇文章整理的先后顺序。

到此这篇关于Spring启动时实现初始化有哪些方式?的文章就介绍到这了,更多相关Spring初始化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java批量修改文件名的实例代码

    Java批量修改文件名的实例代码

    几天前在163公开课上下了一些mp4视频文件。发现课程名和文件名不对应,想到编个程序批量修改。先分析网页源代码将课程名和文件名一一对应,存储在一个文件里,然后使用Java读取该文件进而修改文件名。
    2013-04-04
  • xml与Java对象的转换详解

    xml与Java对象的转换详解

    这篇文章主要介绍了xml与Java对象的转换详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • 详解mybatis.generator配上最新的mysql 8.0.11的一些坑

    详解mybatis.generator配上最新的mysql 8.0.11的一些坑

    这篇文章主要介绍了详解mybatis.generator配上最新的mysql 8.0.11的一些坑,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • Java中双冒号::的作用举例详解

    Java中双冒号::的作用举例详解

    这篇文章主要给大家介绍了关于Java中双冒号::作用的相关资料,双冒号(::)运算符在Java 8中被用作方法引用(method reference),方法引用是与lambda表达式相关的一个重要特性,需要的朋友可以参考下
    2023-11-11
  • Java面向对象之猜拳游戏

    Java面向对象之猜拳游戏

    这篇文章主要为大家详细介绍了Java面向对象之猜拳游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • springboot中的starter及自定义方法详解

    springboot中的starter及自定义方法详解

    这篇文章主要介绍了springboot中的starter及自定义方法详解,Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境(条件)进行自动配置,需要的朋友可以参考下
    2023-11-11
  • springboot 项目使用jasypt加密数据源的方法

    springboot 项目使用jasypt加密数据源的方法

    Jasypt 是一个 Java 库,它允许开发者以最小的努力为他/她的项目添加基本的加密功能,而且不需要对密码学的工作原理有深刻的了解。接下来通过本文给大家介绍springboot 项目使用jasypt加密数据源的问题,一起看看吧
    2021-11-11
  • Spring Boot启动过程(四)之Spring Boot内嵌Tomcat启动

    Spring Boot启动过程(四)之Spring Boot内嵌Tomcat启动

    这篇文章主要介绍了Spring Boot启动过程(四)之Spring Boot内嵌Tomcat启动的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-04-04
  • 关于Spring中@Transactional事务回滚的注意事项

    关于Spring中@Transactional事务回滚的注意事项

    这篇文章主要介绍了关于Spring中@Transactional事务回滚的注意事项,回滚(Rollback)指的是程序或数据处理错误,将程序或数据恢复到上一次正确状态的行为。回滚包括程序回滚和数据回滚等类型,需要的朋友可以参考下
    2023-05-05
  • Java爬虫 信息抓取的实现

    Java爬虫 信息抓取的实现

    本文主要介绍 Java爬虫 信息抓取的实现,这里详细介绍了如何实现该方法,并附示例代码供大家学习参考,有兴趣的小伙伴可以参考下
    2016-09-09

最新评论