假设有这么一个需求,要求在项目启动过程中,完成线程池的初始化,加密证书加载等功能,你会怎么做?如果没想好答案,请接着往下看。今天介绍几种在Spring Boot中进行资源初始化的方式,帮助大家解决和回答这个问题。
MyCommandLineRunner
CommandLineRunner
?接口,并实现它的?run()
?方法,在该方法中编写初始化逻辑@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");
????}
}
MyApplicationRunner
ApplicationRunner
?接口,并实现它的?run()
?方法,在该方法中编写初始化逻辑@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 对象,可以帮助获得更丰富的项目信息。
如果项目中既有实现了?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
?注解同样可以帮助我们完成资源的初始化操作,前提是这些初始化操作不需要依赖于其它Spring beans的初始化工作。
可以看到?@PostConstruct
?注解是用在方法上的,写一个方法测试一下吧。
@PostConstruct
????public?void?init(){
????????System.out.println("@PostConstruct初始化");
????}
@PostConstruct
?注解进行初始化操作的顺序是最快的,前提是这些操作不能依赖于其它Bean的初始化完成。通过添加?@Order
?注解,我们可以改变同层级之间不同Bean的加载顺序。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 就是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");
????????}
????}
}
行高line-height实现单行文本垂直居中 以前一直认为单行文本垂直居中要将高度和...
在讲CSS优先级之前,我们得要了解什么是CSS,CSS是用来做什么的。 首先,我们对C...
Dreamweaver中如何使用Flash影片 1、首先需要我们准备的是一个Flash文件,其次最...
作者 / Krish Vitaldevara,Google Play 信任与安全产品管理总监 多年来,向数十...
一、作用 离线浏览 - 根据文件规则把资源缓存在本地,脱机依然能够访问资源,联...
在ie下设置 css 样式 style="cursor:hand;" 可以正常显示 但是在firefox下就不行...
打开软件,我们按快捷键ctrl+n,建立一个新的文件。 点击常用,选择布局。 点击...
最近在做项目时,发现CSS3中关于动画的技术,自己很少运用在项目中,平时一些列...
背景 京东购物小程序作为京东小程序业务流量的主要入口,承载着许多的活动和页面...
CSS3实现酷炫的3D旋转透视 3D动画效果现在越来越普及,已经被广泛的应用到了各个...