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

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

@Component
public class MyCommandLineRunner implements CommandLineRunner { @Override
public void run(String... args) throws Exception {
System.out.println("...init resources by implements CommandLineRunner");
} }

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

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

控制台打印结果如下。

... start SpringApplication.run()

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.11.RELEASE)
。。。。。。(此处省略一堆打印信息)
2018-05-02 17:01:19.700 INFO 21236 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
...init resources by implements CommandLineRunner
2018-05-02 17:01:19.708 INFO 21236 --- [ main] cn.mariojd.demo.DemoApplication : Started DemoApplication in 2.282 seconds (JVM running for 3.125)
... end SpringApplication.run()

ApplicationRunner

  • 定义初始化类 MyApplicationRunner
  • 实现 ApplicationRunner 接口,并实现它的 run() 方法,在该方法中编写初始化逻辑
  • 注册成Bean,添加 @Component注解即可
  • 示例代码如下:
@Component
public class MyApplicationRunner implements ApplicationRunner { @Override
public void run(ApplicationArguments applicationArguments) throws Exception {
System.out.println("...init resources by implements ApplicationRunner");
} }

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

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

@Component
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner { @Override
public void run(String... args) throws Exception {
System.out.println("...init resources by implements CommandLineRunner");
}
}
@Component
@Order(2)
public class MyApplicationRunner implements ApplicationRunner { @Override
public void run(ApplicationArguments applicationArguments) throws Exception {
System.out.println("...init resources by implements ApplicationRunner");
} }

最终,控制台中打印如下。通过控制台输出我们发现, @Order 注解值越小,该初始化类也就越早执行。

。。。。。。(此处省略一堆打印信息)
2018-05-02 17:27:31.450 INFO 28304 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
...init resources by implements CommandLineRunner
...init resources by implements ApplicationRunner
2018-05-02 17:27:31.453 INFO 28304 --- [ main] cn.mariojd.demo.DemoApplication : Started DemoApplication in 2.086 seconds (JVM running for 2.977)

@PostConstruct

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

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

    @PostConstruct
public void postConstruct() {
System.out.println("... PostConstruct");
}

启动项目,控制台中最终打印如下。

... start SpringApplication.run()

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.11.RELEASE)
。。。。。。(此处省略一堆打印信息)
... PostConstruct
。。。。。。(此处省略一堆打印信息)
2018-05-02 17:40:22.300 INFO 29796 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
...init resources by implements CommandLineRunner
...init resources by implements ApplicationRunner
2018-05-02 17:40:22.303 INFO 29796 --- [ main] cn.mariojd.demo.DemoApplication : Started DemoApplication in 2.387 seconds (JVM running for 3.267)
... end SpringApplication.run()

文末小结

  综上,使用 @PostConstruct 注解进行初始化操作的顺序是最快的,前提是这些操作不能依赖于其它Bean的初始化完成。通过添加 @Order 注解,我们可以改变同层级之间不同Bean的加载顺序。

————————————————
版权声明:本文为CSDN博主「happyJared」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_28804275/article/details/80891941

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. Design Snake Game

    Design a Snake game that is played on a device with screen size = width x height. Play the game onli ...

  2. [转帖]中芯国际14nm秋季量产 7nm工艺或在2020年底问世

    中芯国际14nm秋季量产 7nm工艺或在2020年底问世 https://news.mydrivers.com/1/641/641087.htm 中芯正在发力.. 今年秋天 14nm两场 明年底 7n ...

  3. python商城项目总结

    项目概括 本项目用于针对Django框架的练习,主要分为前端和后端两部分.前端负责用户注册.登录.商品展示以及添加购物车和显示订单列表的功能:后端负责会员信息.商品类别.商品信息的增删改查以及订单状态 ...

  4. vue使用axios进行ajax请求

    以前都用resource进行ajax请求,现在官方推荐使用axios,所以现在更换插件.这篇文章主要描写如何在项目中引入axios以及简单地使用axios进行ajax请求. 第一步,需要通过npm安装 ...

  5. Java EE Servlet相关的两个包

    Servlet in Java EE 在Java EE的规范API中(链接),Servlet相关联的最重要的两个Package为: 1.javax.servlet 包含了一系列接口和类,他们在一个Se ...

  6. leecode 刷题(32)-- 链表的中间节点

    leecode 刷题(32)-- 链表的中间节点 描述: 给定一个带有头结点 head 的非空单链表,返回链表的中间结点. 如果有两个中间结点,则返回第二个中间结点. 示例 1: 输入:[1,2,3, ...

  7. C# 使用Emit实现动态AOP框架 进阶篇之异常处理

    目  录 C# 使用Emit实现动态AOP框架 (一) C# 使用Emit实现动态AOP框架 (二) C# 使用Emit实现动态AOP框架 (三) C# 使用Emit实现动态AOP框架 进阶篇之异常处 ...

  8. 搭建自己的框架WedeNet(二)

    WedeNet2018.Infrastructure-基础设施层:结构如下: Tools结构如下: 考虑到系统可能会有多个数据上下文(暂时以两个为例),所以根据需要定义两个T4模板用来生成对应的ent ...

  9. golang(9):网络编程 & redis

    网络编程 TCP/IP 协议: . TCP(传输控制协议) -- 应用程序之间通信 . UDP(用户数据包协议)-- 应用程序之间的简单通信 . IP(网际协议) -- 计算机之间的通信 . DHCP ...

  10. clientHeight和offsetHeight

    clientHeight:包括padding但不包括border.水平滚动条.margin的元素的高度.对于inline的元素这个属性一直是0,单位px,只读元素. offsetHeight:包括pa ...