Spring Boot(三):Spring Boot中的事件的使用 与Spring Boot启动流程(Event 事件 和 Listeners监听器)
前言:在讲述内容之前 希望大家对设计模式有所了解 即使你学会了本片的内容 也不知道什么时候去使用 或者为什么要这样去用
观察者模式:
观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主体是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。观察者模式不仅被广泛应用于软件界面元素之间的交互,在业务对象之间的交互、权限管理等方面也有广泛的应用
观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。(以上源于百度)
已经熟悉设计模式的可以直接向下阅读 对不熟悉的 希望通过上述内容 你们可以有一定的了解 通俗点说 观察者模式 是设计框架的一种
当然我们的Spring Boot当然也不会放过这么好的设计模式 那么Spring Boot中又有哪些地方使用到了
1.ApplicationStartingEvent
当应用启动还没有进行任何处理时,在对所有的监听器做初始化的时候发送的事件
public ConfigurableApplicationContext run(String... args) {
//记录服务启动事件
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
//开启awt的headless模式
//Headless模式是系统的一种配置模式。在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式
this.configureHeadlessProperty();
//获取监听器列表
SpringApplicationRunListeners listeners = this.getRunListeners(args);
启动所有监听器
listeners.starting();
.................
}
此时监听列表中只有一个监听事件为EventPublishingRunListener
它的作用就是通知Spring Boot项目开始启动
2.ApplicationEnvironmentPreparedEvent
当已获取的了所有Spring Context上下文信息 但是此时还没有进行创建
此时Spring Boot开始启动 EventPublishingRunListener会发送ApplicationEnvironmentPreparedEvent事件 告诉Spring Boot应用环境已经准备就绪 准备做后续处理 监听此事件的监听器是ConfigFileApplicationListener
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
//获取环境 资源 加载器
List<EnvironmentPostProcessor> postProcessors = this.loadPostProcessors();
postProcessors.add(this);
//对Order的大小进行排序 装载
AnnotationAwareOrderComparator.sort(postProcessors);
//使用迭代器 根据顺序开始执行 环境 资源 的配置
Iterator var3 = postProcessors.iterator();
while(var3.hasNext()) {
EnvironmentPostProcessor postProcessor = (EnvironmentPostProcessor)var3.next();
postProcessor.postProcessEnvironment(event.getEnvironment(), event.getSpringApplication());
}
}
3.ApplicationContextInitializedEvent
测试Spring Context上下文已经初始化完毕 但是此时上下文是的空的
开始向Spring上下文装填内容
public void contextPrepared(ConfigurableApplicationContext context) {
//获取当前所有有关的上下文的监听器
Iterator var2 = this.listeners.iterator();
while(var2.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
//通知
listener.contextPrepared(context);
}
}
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
//向上下文中装填配置参数
//context.setEnvironment(environment);
//向应用中装填上下文
this.postProcessApplicationContext(context);
//进行初始化参数装填
this.applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
Set<Object> sources = this.getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
this.load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
4.ApplicationPreparedEvent
应用加载完毕
public void contextLoaded(ConfigurableApplicationContext context) {
ApplicationListener listener;
//相容器中装填已经初始化的上下文对象
for(Iterator var2 = this.application.getListeners().iterator(); var2.hasNext(); context.addApplicationListener(listener)) {
listener = (ApplicationListener)var2.next();
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware)listener).setApplicationContext(context);
}
}
//通知
this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
5.ApplicationStartedEvent
应用初始化完成
public void started(ConfigurableApplicationContext context) {
//通知
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context));
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
6.ApplicationReadyEvent
应用加载完毕
public void running(ConfigurableApplicationContext context) {
context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context));
}
这就是Spring在启动的时候 发生的事件交互 最直观的我们可以看出 当一个具体的功能实现完毕之后 创建事件 去通知下一个阶段去做相对的事情 这样子比在一个方法里面 去直接调用好得多 并且可以支持广播模式(一对多)
当然在Spring Boot中使用观察者模式 也非常简单 首先我们创建一个名为旅游的事件
@Data
public class TravelEvent {
private String money;
private String location;
private String sex;
}
当我们需要去旅行时 需要带钱 带男/女朋友 去什么地方游玩
注册一个监听类用来监听我们发出的事件
1.监听类的实例必须由Spring容器管理 切必须有实例 否则无法监听到事件的发生
2.在方法上使用@EventListener(事件类)注解 可以将事件实例当做入参 进行业务处理
3.使用ApplicationEventPublisher发送事件 进行测试
@Component
public class TravelEventListener {
@EventListener(TravelEvent.class)
public void location(TravelEvent travelEvent){
System.out.println("地方:"+travelEvent.getLocation());
}
@EventListener(TravelEvent.class)
public void sex(TravelEvent travelEvent){
System.out.println("朋友:"+travelEvent.getSex());
}
@EventListener(TravelEvent.class)
public void money(TravelEvent travelEvent){
System.out.println("钱:"+travelEvent.getMoney());
}
}
@RestController
@RequestMapping("/event")
public class EventController {
@Autowired
ApplicationEventPublisher applicationEventPublisher;
@PostMapping("/travel")
public String goTravel(@RequestBody TravelEvent travelEvent){
applicationEventPublisher.publishEvent(travelEvent);
return "ok";
}
}
最后 Spring Boot中启动时 所发生的事件 已经在Spring Boot中如何使用事件已经讲完了 可以看出在Spring Boot中使用观察者模式 还是非常方便的 作为一名程序员 尤其是后台人员务必利用好设计模式 如果一个项目 没有使用任何设计模式 那么还不如去写面向过程 一旦有需求的变更 我们就可能成为 外行眼里吐槽的 加班狗 地中海等等......
Spring Boot(三):Spring Boot中的事件的使用 与Spring Boot启动流程(Event 事件 和 Listeners监听器)的更多相关文章
- SpringBoot启动流程分析(三):SpringApplication的run方法之prepareContext()方法
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- Slickflow.NET 开源工作流引擎高级开发(一) -- 流程外部事件的调用和变量存储实现
前言:流程实现基本流转功能外,通常也需要调用外部事件,用于和业务系统的交互,同时存储一些流程变量,用于追踪和记录业务数据变化对流程流转的影响. 1. 流程事件 流程执行过程中,伴随各种事件的发生,而且 ...
- Spring boot(三)在Spring boot中Redis的使用
spring boot对常用的数据库支持外,对nosql 数据库也进行了封装自动化. redis介绍 Redis是目前业界使用最广泛的内存数据存储.相比memcached,Redis支持更丰富的数据结 ...
- 精选Spring Boot三十五道必知必会知识点
Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家.本文精选了三十五个常见的Spring Boot知识点,祝你一臂之力! 问题一 Spr ...
- Java精选面试题之Spring Boot 三十三问
Spring Boot Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家. 问题一: Spring Boot.Spring MVC 和 ...
- 漫谈Spring Security 在Spring Boot 2.x endpoints中的应用(一)
Spring Boot 2.x极大简化了默认的安全配置,并不是说有很多安全相关的配置,现在你只需要提供一个WebSecurityConfigurerAdapter继承类这样一个简单的操作,Spring ...
- Spring Boot 监听 Activemq 中的特定 topic ,并将数据通过 RabbitMq 发布出去
1.Spring Boot 和 ActiveMQ .RabbitMQ 简介 最近因为公司的项目需要用到 Spring Boot , 所以自学了一下, 发现它与 Spring 相比,最大的优点就是减少了 ...
- spring boot 项目从配置文件中读取maven 的pom.xml 文件标签的内容。
需求: 将pom.xml 文件中的版本号读取到配置文件并打印到日志中. 第一步: 在pom.xml 中添加以下标签. 第二步: 将version 标签的值读取到配置文件中 这里使用 @@ 而不是 ...
- Spring boot(三)整合mybaties+thymeleaf实现基础crud
工程结构: 首先在pom文件中引入依赖 <?xml version="1.0" encoding="UTF-8"?> <project xml ...
随机推荐
- mysql-redis连接
# log 数据库连接 class LogMysql(object): conn = None cursor = None def __init__(self): self.conn = pymysq ...
- V $ BACKUP_DATAFILE
V$BACKUP_DATAFILE 从控制文件显示有关备份集中的控制文件和数据文件的信息. 柱 数据类型 描述 RECID NUMBER 备份数据文件记录ID STAMP NUMBER 备份数据文件记 ...
- CVPR 2020目标跟踪多篇开源论文(上)
CVPR 2020目标跟踪多篇开源论文(上) 1. SiamBAN:面向目标跟踪的Siamese Box自适应网络 作者团队:华侨大学&中科院&哈工大&鹏城实验室&厦门 ...
- AI芯片体系结构目标图形处理
AI芯片体系结构目标图形处理 AI chip architecture targets graph processing 可编程图形流处理器(GSP)能够执行"直接图形处理.片上任务图管理和 ...
- python读取配置文件,yaml模块读取yml文件
ymal文件编写语法参考http://www.ruanyifeng.com/blog/2016/07/yaml.html ymal在python中的安装:pip install pyyaml yml文 ...
- 基于Spring Boot的在线问卷调查系统的设计与实现+论文
全部源码下载 # 基于Spring Boot的问卷调查系统 ## 介绍 > * 本项目的在线问卷调查调查系统是基于Spring Boot 开发的,采用了前后端分离模式来开发. > * 前端 ...
- 基于Android平台的图书管理系统的制作(1)
在学习了郭神的第一行代码前半段之后,想通过一次实践来完成对已学知识的巩固.于是码下了这个图书管理系统客户端. IDE Android studio,语言 JAVA.XML: 在刚开始设计的时候对于这个 ...
- 【NX二次开发】不健全的双击按钮。
为什么说不健全,是因为 双击按钮时会先运行单击事件,这个后面再解决.但是模仿某公司的图层操作工具是没有问题了,因为这个工具运行双击事件时本来就需要运行单击事件,不仔细看容易被唬住. 图层操作工具(双击 ...
- 有了Java8的“+”真的可以不要StringBuilder了吗
最近在头条上看到一篇帖子,说Java8开始,字符串拼接时,"+"会被编译成StringBuilder,所以,字符串的连接操作不用再考虑效率问题了,事实真的是这样吗?要搞明白,还是要 ...
- Luat Inside | 致敬经典,使用Air724UG制作简易贪吃蛇
作者简介: 打盹的消防车--活跃于Luat社群的新生代全能开发者,东北小伙儿爽朗幽默.好学敏思,更是实力行动派.幼年曾手握火红炽铁而后全然无恙,堪称魔幻经历:如今热衷于各类嵌入式软硬件研究,快意物联江 ...