三 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:Spring Boot中的事件的使用 与Spring Boot启动流程(Event 事件 和 Listeners监听器)

文章插图
它的作用就是通知Spring Boot项目开始启动
三 Spring Boot:Spring Boot中的事件的使用 与Spring Boot启动流程(Event 事件 和 Listeners监听器)

文章插图
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中使用观察者模式 也非常简单 首先我们创建一个名为旅游的事件
@Datapublic class TravelEvent {private String money;private String location;private String sex;}当我们需要去旅行时 需要带钱 带男/女朋友 去什么地方游玩
注册一个监听类用来监听我们发出的事件
1.监听类的实例必须由Spring容器管理 切必须有实例 否则无法监听到事件的发生2.在方法上使用@EventListener(事件类)注解 可以将事件实例当做入参 进行业务处理3.使用ApplicationEventPublisher发送事件 进行测试@Componentpublic 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());}}【三 Spring Boot:Spring Boot中的事件的使用 与Spring Boot启动流程(Event 事件 和 Listeners监听器)】@RestController@RequestMapping("/event")public class EventController {@AutowiredApplicationEventPublisher applicationEventPublisher;@PostMapping("/travel")public String goTravel(@RequestBody TravelEvent travelEvent){applicationEventPublisher.publishEvent(travelEvent);return "ok";}}
三 Spring Boot:Spring Boot中的事件的使用 与Spring Boot启动流程(Event 事件 和 Listeners监听器)

文章插图
三 Spring Boot:Spring Boot中的事件的使用 与Spring Boot启动流程(Event 事件 和 Listeners监听器)

文章插图
最后 Spring Boot中启动时 所发生的事件 已经在Spring Boot中如何使用事件已经讲完了 可以看出在Spring Boot中使用观察者模式 还是非常方便的 作为一名程序员 尤其是后台人员务必利用好设计模式 如果一个项目 没有使用任何设计模式 那么还不如去写面向过程 一旦有需求的变更 我们就可能成为 外行眼里吐槽的 加班狗 地中海等等......