麻烦转载表明备注,谢谢。
由于项目存在与硬件设备的多种交互,产生了以下业务内容:1、需要在项目启动时初始化特定的设备;2、特定设备的特定数值在发生变化时触发特定事件执行业务逻辑
设计的初步大体思路为观察者模式或者监听来实现,考虑到使用观察者模式存在主题的列表维护、观察者的列表维护、主题更改或者取消后需要同时对于观察者进行代码更新的紧耦合的问题,决定采用基于SpringApplication的相关监听方式来实现。
了解SpringBoot项目启动流程源码的同学应该知道以下几个名词:
1、SpringApplicationListener、SpringApplicationEvent
2、CommandLineRunner
实现一:
其中SpringApplicationListener、SpringApplicationEvent主要用于SpringBoot项目启动时加载准备SpringApplicationContext、自动配置和Environment时的监听器和事件,其中关于SpringApplicationEvent其实现为如下:
分别对应:
1、ApplicationContext的初始化事件
2、ApplicationEnvironment的准备事件
3、Application加载失败事件
4、Application准备事件
5、Application就绪事件
6、Application启动事件
7、Application启动中事件
这些事件均会被SpringApplicationListener所监听到,我们可以选择对应的事件触发时机进行我们的业务相关处理,这个需要开发者自己选择,以下列出我们的使用方式:
我们选择了就绪事件,事件执行在SpringApplication所有的前置加载准备完成后执行。需要注意的是:
1、方法的线程阻塞问题,前面方法阻塞,会导致后续方法等待的问题。
2、我们使用的是Spring自己的启动监听器,如果需要自己构建自定义事件的发布使用自定义监听器来实现的话需要自己实现事件发布、事件、事件监听器【具体参考我的上一篇监听器的实现博客内容】
实现二:
CommandLineRunner
熟悉SpringBoot启动源码的同学应该知道,在源码中当所有的配置项加载完成后会有执行这么一个方法
看方法名知道这里是回调的一个方法,里面对于监听线程做了一个分类【分为ApplicationRunner、CommandLineRunner】,其中ApplicationRunner我们不陌生,是Spring启动时加载配置的状态的监听,那么CommandLineRunner就是回调监听了,具体回调什么?我们看源码介绍:
源码说明这是回调运行Bean对象的方法,再看源码
这个方法内部调用了CommandLineRunner,上面都是SpringBoot启动时配置的加载和IOC容器的合并、自动配置项的加载,加载完成后调用此方法,所以我们知道了这个是在SpringBoot启动完成后的回调监听事件。
所以,被CommandLineRunner所监听的事件都是在SpringBoot加载配置完成后执行的一个回调监听,自然我们可以用到它来实现一些我们的不关心成功或失败的业务。
这里举一个简单的例子:
执行结果:
值得注意的是:
CommandLineRunner需要关两点:
1、所有CommandLineRunner的执行时点在SpringBoot应用的ApplicationContext完全初始化开始工作之后(可以认为是main方法执行完成之前最后一步)。
2、只要存在于当前SpringBoot应用的ApplicationContext中的任何CommandLineRunner,都会被加载执行(不管你是手动注册这个CommandLineRunner到IOC容器,还是自动扫描进去的)。
与其他几个扩展点接口类型相似,建议CommandLineRunner的实现类使用@org.springframework.core.annotation.Order 进行标注或者实现 org.springframework.core.Ordered 接口,便于对它们的执行顺序进行调整,这其实十分重要,我们不希望顺序不当的 CommandLineRunner 实现类阻塞了后面其他 CommandLineRunner 的执行。