当前位置: 监察器 >> 监察器市场 >> SpringBoot中,如何自定义Spr
SpringBoot中,如何自定义Spring应用运行时监听器?无头模式Headless是什么意思?
开始
今天,我们来聊聊SpringBoot自己的Spring应用运行时监听器。
StopWatch
StopWatch,直译为跑表,就是个简单的计时器。开始时记个时间,结束时记个时间,就可以把整体运行消耗的时间统计出来。
这里面有个点是,计时器包含一个currentTaskName,当前任务名称。在启动start时,如果currentTaskName不为空,便认为应用已经启动。在停止stop时,如果currentTaskName为空,便认为应用已经停止。
SpringBootExceptionReporter
SpringBoot异常报告器。一个独立的接口,要求其实现类实现一个reportException方法,该方法接受一个Throwable参数。报告异常,顾名思义,实现类在该方法中的核心逻辑应该是对异常的处理,处理方式主要为报告。
Headless
无头模式。你会买一台没有显示屏、键盘或鼠标的电脑吗?当然不会。没有显示屏,还怎么看高清优质的动作片?但是,当一台电脑作为服务器时,我们其实主要使用的是其CPU的计算能力,内存、硬盘的存储能力,网络IO能力。至于它有没有显示屏,键盘或者鼠标,这对于我们来说,其实并不是必须的。我们把这样的服务器称之为“无头”的服务器。
但是,有时候,我们可能又需要利用显示屏、键盘或鼠标等,实现一些功能,那么,在“无头”的服务器上怎么办呢?
没关系,Java帮我们解决。JDK中包含一些jar包,这些jar可以模拟显示屏、键盘或鼠标的某些功能,以帮助我们达到某些目的。
所以,当你想要使用这些功能时,就需要将服务设置为无头模式。
Run
SpringBoot的SpringApplication完成构造后,就会去执行其run方法,最终执行的run方法是以一个String变长数组为参数的run方法。我们称之为主run方法。
在主run方法中,首先我们看到的是新建了一个秒表实例,然后,将服务设置成了无头模式。
在设置无头模式时,调用了System中的setProperty和getProperty方法,这两个方法,可以帮助我们设置或获取系统属性。注意,这里的系统指的是JREsystem,而不是OS。你可以把这两个方法操作的目标区域想象成一个存放全局变量的容器,而serProperty和getProperty就是对全局变量的操作。
获取运行时监听器列表
监听器用于监听系统状态的改变,而SpringApplicationRunListener,则是专门用来SpringApplication,即Spring应用的状态的改变。
在SpringApplicationRunListener这个接口中,规定了7个方法,分别对应了Spring应用的7种状态,它们分别如下:
starting:启动中状态。看源码,你会发现,运行时监听器列表获取完成后,就会调用该方法。也就是说,启动中状态是一个SpringBoot应用执行run方法后,最先进入的一个状态。
environmentPrepared:环境准备就绪状态。运行环境准备就绪后,应用进入该状态,调用一次该方法。此时,应用环境准备就绪,但是应用上下文还没有创建。
contextPrepared:应用上下文就绪状态。应用上下文创建完成后,应用进入该状态,调用一次该方法。此时,应用上下文创建完成,但是应用资源还未加载。
contextLoaded:应用上下文载入状态。应用上下文载入后,应用进入该状态,调用一次该方法。此时,应用上下文载入完毕,但是还没有刷新。
started:应用启动完成状态。应用启动完成后,应用进入该状态,调用该方法。此时,应用刷新完成,但是,我们自定义的一些应用启动后执行的方法还没有执行,如通过实现CommandLineRunner或ApplicationRunner接口定义的方法。
running:应用运行中状态。我们自定义的一些应用启动后执行的方法执行完成,应用进行运行中状态。观察SpringApplication的主run方法,可以发现,在方法的最后,调用了监听器的running方法。
failed:应用失败状态。应用启动失败,应用变为失败状态。
以上,就是运行时监听器中的7个方法,对应SpringBoot启动到运行的7种状态。在主run方法,通过getRunListeners方法来获取运行时监听器列表。观察getRunListeners,我们发现,SpringBoot的SpringApplication获取运行时监听器的逻辑和获取初始化器及监听器的逻辑是基本一致的,也是从spring.factories文件中来取。唯一不同的是,获取到的运行时监听器列表,最终被放到一个叫SpringApplicationRunListeners的对象里,看源码就知道,这个对象没什么实质功能,只是为了方便给统一的方法来调用每个运行时监听器中的同一方法。
自定义运行时监听器
了解了自定义运行时监听器的获取方式,我们可以像自定义初始化器或监听器一样,自定义一个运行时监听器。
文件目录结构如下:
运行时监听器目录结构MyRunListener代码如下:
注意这个类中,我们不光实现了SpringApplicationRunListener接口所要求的7个方法,还添加了一个以SpringApplication和一个变长字符串数组为参数的构造方法。那么,在哪里规定,必须要有这样一个构造方法呢?注意getRunListeners中的代码:
注意types的定义,这个定义,决定了如果没有相应的构造方法,就会报错。
spring.factories文件中配置如下:
启动应用,得到控制台日志如下:
运行时监听器日志总结
Spring应用运行时监听器和普通的监听器相比,它给不同的事件提供了不同的接口方法,使用起来会更加清晰明了。
相关
SpringBoot的优点,有哪些值得我们使用的地方
SpringBoot启动流程之断言和web应用类型
Spring中,ApplicationContext的继承体系
自定义SpringApplication初始化器和监听器