假设有这么一个需求,要求在项目启动过程中,完成线程池的初始化,加密证书加载等功能,你会怎么做?如果没想好答案,请接着往下看。今天介绍几种在Spring Boot中进行资源初始化的方式,帮助大家解决和回答这个问题。

CommandLineRunner

  • 定义初始化类 MyCommandLineRunner
  • 实现 CommandLineRunner 接口,并实现它的 run() 方法,在该方法中编写初始化逻辑
  • 注册成Bean,添加 @Component注解即可
  • 示例代码如下:
package cn.zh.controller;

import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Componentpublic class MyCommandLineRunner implements CommandLineRunner {
   
    @Override
    public void run(String... args) throws Exception {
        System.out.println("项目初始化---------------11");
    }
}

实现了 CommandLineRunner 接口的 Component 会在所有 Spring Beans 初始化完成之后, 在 SpringApplication.run() 执行之前完成。下面通过加两行打印来验证我们的测试。

package cn.zh;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ProcApplication {

    public static void main(String[] args) {
        System.out.println("...start SpringApplication.run");
        SpringApplication.run(ProcApplication.class,args);
        System.out.println("....end SpringApplication.run");
    }
}

ApplicationRunner

  • 定义初始化类 MyApplicationRunner
  • 实现 ApplicationRunner 接口,并实现它的 run() 方法,在该方法中编写初始化逻辑
  • 注册成Bean,添加 @Component注解即可
  • 示例代码如下:
package cn.zh.controller;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("项目初始化二---------");
    }

   
}

可以看到,通过实现 ApplicationRunner 接口,和通过实现 CommandLineRunner 接口都可以完成项目的初始化操作,实现相同的效果。两者之间唯一的区别是 run() 方法中自带的形参不相同,在 CommandLineRunner 中只是简单的String... args形参,而 ApplicationRunner 则是包含了 ApplicationArguments 对象,可以帮助获得更丰富的项目信息。

@Order

如果项目中既有实现了 ApplicationRunner 接口的初始化类,又有实现了 CommandLineRunner 接口的初始化类,那么会是哪一个先执行呢?测试告诉我们,答案是实现了 ApplicationRunner 接口的初始化类先执行,我想这点倒是不需要大家过分去关注为什么。但如果需要改变两个初始化类之间的默认执行顺序,那么使用 @Order 注解就可以帮助我们解决这个问题。

@Component
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {
    /**
     * Callback used to run the bean.
     *
     * @param args incoming main method arguments
     * @throws Exception on error
     */
    @Override
    public void run(String... args) throws Exception {
        System.out.println("项目初始化---------------11");
    }
}
@Component
@Order(2)
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("项目初始化二---------");
    }

    @PostConstruct
    public void init(){
        System.out.println("@PostConstruct初始化");
    }
}

@PostConstruct

使用 @PostConstruct 注解同样可以帮助我们完成资源的初始化操作,前提是这些初始化操作不需要依赖于其它Spring beans的初始化工作。

可以看到 @PostConstruct 注解是用在方法上的,写一个方法测试一下吧。

@PostConstruct
    public void init(){
        System.out.println("@PostConstruct初始化");
    }
  • 注意:

    • 只有一个非静态方法能使用此注解
    • 被注解的方法不得有任何参数
    • 被注解的方法返回值必须为void
    • 被注解方法不得抛出已检查异常
    • 此方法只会被执行一次
  • 综上,使用 @PostConstruct 注解进行初始化操作的顺序是最快的,前提是这些操作不能依赖于其它Bean的初始化完成。通过添加 @Order 注解,我们可以改变同层级之间不同Bean的加载顺序。

InitializingBean

InitializingBean 是 Spring 提供的一个接口,只包含一个方法 afterPropertiesSet()。凡是实现了该接口的类,当其对应的 Bean 交由 Spring 管理后,当其必要的属性全部设置完成后,Spring 会调用该 Bean 的 afterPropertiesSet()。

@Component
public class MyListener1 implements InitializingBean {
    @Autowired
    private ShopInfoMapper shopInfoMapper;
    @Override
    public void afterPropertiesSet() {
        //使用spring容器中的bean
        //System.out.println(shopInfoMapper.selectById("1").getShopName());
        System.out.println("项目启动OK");
    }
}

ApplicationListener

ApplicationListener 就是spring的监听器,能够用来监听事件,典型的观察者模式。如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。这种事件机制都必须需要程序显示的触发。

其中spring有一些内置的事件,当完成某种操作时会发出某些事件动作。比如监听ContextRefreshedEvent事件,当所有的bean都初始化完成并被成功装载后会触发该事件,实现ApplicationListener接口可以收到监听动作,然后可以写自己的逻辑。

同样事件可以自定义、监听也可以自定义,完全根据自己的业务逻辑来处理。所以也能做到资源的初始化加载。

@Component
public class MyListener1 implements ApplicationListener {
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        
        //打印出每次事件的名称
        System.out.println(applicationEvent.toString());
        
        if (applicationEvent instanceof ApplicationReadyEvent) {
            System.out.println("项目启动OK");
        }
    }
}

Spring Boot 中初始化资源的几种方式的更多相关文章

  1. Spring Boot 中初始化资源的几种方式(转)

    假设有这么一个需求,要求在项目启动过程中,完成线程池的初始化,加密证书加载等功能,你会怎么做?如果没想好答案,请接着往下看.今天介绍几种在Spring Boot中进行资源初始化的方式,帮助大家解决和回 ...

  2. Spring Boot中初始化资源的几种方式

    CommandLineRunner 定义初始化类 MyCommandLineRunner 实现 CommandLineRunner接口,并实现它的 run()方法,在该方法中编写初始化逻辑 注册成Be ...

  3. Spring Boot 中实现定时任务的两种方式

    在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Qua ...

  4. spring boot中读取配置文件的两种方式

    application.properties test.name=测试 test.url=www.test.com 1.@Value注解 在controller里可以这样直接调用 @Value(&qu ...

  5. Spring Boot定义系统启动任务的两种方式

    Spring Boot定义系统启动任务的两种方式 概述 如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web ...

  6. Spring MVC中forward请求转发2种方式(带参数)

    Spring MVC中forward请求转发2种方式(带参数) http://www.51gjie.com/javaweb/956.html  

  7. JavaWeb应用中初始化Log4j的两种方式

    本文主要介绍了普通JavaWeb应用(基于Tomcat)中初始化Log4j的两种方式: 1.通过增加 InitServlet ,设置令其自启动来初始化 Log4j . 2.通过监听器 ServletC ...

  8. Spring Boot中静态资源(JS, 图片)等应该放在什么位置

    Spring Boot的静态资源,比如图片应该放在什么位置呢, 如果你放在传统WEB共的类似地方, 比如webapp或者WEB-INF下,你会得到一张示意文件未找到的破碎图片.那应该放哪里呢? 百度一 ...

  9. Spring3实战第二章第一小节 Spring bean的初始化和销毁三种方式及优先级

    Spring bean的初始化和销毁有三种方式 通过实现 InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法: 优先级第二通过 <bean& ...

随机推荐

  1. 动画推荐-By胡罗

    常用16种视图切换动画 系统自带的动画,结构清晰,代码简单 带弹性动画的分享菜单-https://github.com/KittenYang/KYShareMenu 第一眼以为用的是Pop动画,看了下 ...

  2. 范数||x||(norm)笔记

    1. 范数的含义和定义 范数是具有"长度"概念的函数.在线性代数.泛函分析及相关领域,是一个函数,它为向量空间内的所有向量赋予非零的正的长度或大小.另一方面,半范数可以为非零的向量 ...

  3. Azure AD Domain Service(二)为域服务中的机器配置 Azure File Share 磁盘共享

    一,引言 Azure File Share 是支持两种认证方式的! 1)Active Directory 2)Storage account key 记得上次分析的 "Azure File ...

  4. 5.1 Paralles 为虚拟机设置静态ip

    一.配置独立ip的环境 前面研究了k8s的组件,核心概念,网络模型,都了解了一遍,现在就要进入实战了,摆在面前的一座大山,必须克服才行---虚拟机搭建,及网络环境配置. 先说说本文的运行环境: mac ...

  5. Solution -「CF 1391E」Pairs of Pairs

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的无向图,在其上找到一条包括不少于 \(\lceil\frac{n}2\rceil\ ...

  6. 在超算系统上使用sbatch提交MXNet分布式训练任务

    在超算系统上运行MXNet分布式训练任务时,面临着一个IP地址相关的问题.我们在提交MXNet的分布式任务时,需要知道各个GPU节点的IP地址,把这些IP地址放到一个hosts文件中,以供分布式训练使 ...

  7. MySQL架构原理之存储引擎InnoDB_Redo Log和BinLog

    Redo Log和Binlog是MySQL日志系统中非常重要的两种机制,有很多相似之处同时也有差别,本文探究两者细节和区别. 一.Redo Log 1.Redo Log介绍 Redo:顾名思义就是重做 ...

  8. 使用 Spring Cloud Jaeger 进行分布式跟踪

    在本文中,学习如何实现 Jaeger(基于 OpenTracing 和 Spring Boot 应用程序)以及如何使用 Jaeger UI 可视化跟踪. 介绍 在本文中,我们将探讨如何使用 Jaege ...

  9. Docker 设置国内镜像源

    创建或修改 /etc/docker/daemon.json 文件,修改为如下形式    # vi /etc/docker/daemon.json    {        "registry- ...

  10. 网络测试仪实操手册 RENIX 机框管理

    本文主要阐述信而泰BIGTAO系列 网络测试仪器机框相关操作方法.文章分为机框添加.机框删除.机框重启.机框关机四部分. 第一部分:机框添加 1.添加过程 1.1打开软件 1.2添加端口 1.3输入I ...