springboot学习----事件监听

来源:互联网 发布:便笺元数据损坏没事不 编辑:程序博客网 时间:2024/06/03 17:23

起源

Spring的Application拥有发布事件并且注册事件监听器的能力,拥有一套完整的事件发布和监听机制。在Java中,通过java.util. EventObject来描述事件,通过java.util. EventListener来描述事件监听器,在众多的框架和组件中,建立一套事件机制通常是基于这两个接口来进行扩展。

概念

  • ApplicationEvent就是Spring的事件接口
  • ApplicationListener就是Spring的事件监听器接口,所有的监听器都实现该接口
  • ApplicationEventPublisher是Spring的事件发布接口,ApplicationContext实现了该接口
  • ApplicationEventMulticaster就是Spring事件机制中的事件广播器,默认实现SimpleApplicationEventMulticaster

在Spring中通常是ApplicationContext本身担任监听器注册表的角色,在其子类AbstractApplicationContext中就聚合了事件广播器ApplicationEventMulticaster和事件监听器ApplicationListnener,并且提供注册监听器的addApplicationListnener方法。

执行流程

当一个事件源产生事件时,它通过事件发布器ApplicationEventPublisher发布事件,然后事件广播器ApplicationEventMulticaster会去事件注册表ApplicationContext中找到事件监听器ApplicationListnener,并且逐个执行监听器的onApplicationEvent方法,从而完成事件监听器的逻辑。

默认启动事件

  • ApplicationStartedEvent
  • ApplicationEnvironmentPreparedEvent
  • ApplicationPreparedEvent
  • ApplicationFailedEvent

源码片段

AbstractApplicationContext实现了ApplicationEventPublisher接口方法,通过ApplicationEventMulticaster广播事件

public void publishEvent(ApplicationEvent event) {        Assert.notNull(event, "Event must not be null");        if(this.logger.isTraceEnabled()) {            this.logger.trace("Publishing event in " + this.getDisplayName() + ": " + event);        }        this.getApplicationEventMulticaster().multicastEvent(event);        if(this.parent != null) {            this.parent.publishEvent(event);        }    }

spring boot 系统事件分发

EventPublishingRunListener中通过initialMulticaster广播事件

public ConfigurableApplicationContext run(String... args) {        StopWatch stopWatch = new StopWatch();        stopWatch.start();        ConfigurableApplicationContext context = null;        Object analyzers = null;        this.configureHeadlessProperty();        //获取RunListeners 通过SpringFactoriesLoader获取spring.factories配置        //默认实现类EventPublishingRunListener        SpringApplicationRunListeners listeners = this.getRunListeners(args);        //发布ApplicationStartingEvent事件          listeners.starting();        try {            DefaultApplicationArguments ex = new DefaultApplicationArguments(args);            //发布ApplicationEnvironmentPreparedEvent事件            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, ex);            Banner printedBanner = this.printBanner(environment);            context = this.createApplicationContext();            new FailureAnalyzers(context);            //发布ApplicationPreparedEvent事件            this.prepareContext(context, environment, listeners, ex, printedBanner);             this.refreshContext(context);            this.afterRefresh(context, ex);            //发布ApplicationReadyEvent事件            listeners.finished(context, (Throwable)null);            stopWatch.stop();            if(this.logStartupInfo) {                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);            }            return context;        } catch (Throwable var9) {            this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);            throw new IllegalStateException(var9);        }    }

EventPublishingRunListener 以starting为例,发布ApplicationStartedEvent启动事件

 public void starting() {        this.initialMulticaster.multicastEvent(new ApplicationStartedEvent(this.application, this.args));    }

SimpleApplicationEventMulticaster

 public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {        ResolvableType type = eventType != null?eventType:this.resolveDefaultEventType(event);        //根据事件类型获取事件对应的ApplicationListener        Iterator var4 = this.getApplicationListeners(event, type).iterator();        while(var4.hasNext()) {            final ApplicationListener listener = (ApplicationListener)var4.next();            //如果配置了线程池,则异步执行listener的onApplicationEvent方法            Executor executor = this.getTaskExecutor();            if(executor != null) {                executor.execute(new Runnable() {                    public void run() {                        SimpleApplicationEventMulticaster.this.invokeListener(listener, event);                    }                });            } else {                this.invokeListener(listener, event);            }        }    }//执行监听中onApplicationEvent方法protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {        ErrorHandler errorHandler = this.getErrorHandler();        if(errorHandler != null) {            try {                listener.onApplicationEvent(event);            } catch (Throwable var7) {                errorHandler.handleError(var7);            }        } else {            try {                listener.onApplicationEvent(event);            } catch (ClassCastException var8) {                String msg = var8.getMessage();                if(msg != null && !msg.startsWith(event.getClass().getName())) {                    throw var8;                }                Log logger = LogFactory.getLog(this.getClass());                if(logger.isDebugEnabled()) {                    logger.debug("Non-matching event type for listener: " + listener, var8);                }            }        }    }

参考

http://liuxiamai.iteye.com/blog/2322197
http://blog.csdn.net/nution/article/details/72765813
http://blog.csdn.net/chszs/article/details/49097919

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 网页游戏打开说脚本错误怎么办 电脑玩游戏出现闪屏怎么办 玩游戏时出现窗口化怎么办 玩游戏时出现输入不支持怎么办 电脑玩游戏出现蓝屏怎么办 谷歌商店网页版进不去怎么办 谷歌商店为什么打不开怎么办 玩lol突然卡顿怎么办 手机上路由器管理页面打不开怎么办 苹果电脑开机页面密码打不开怎么办 逆战活动页面打不开怎么办 电脑玩lol网络卡怎么办 ios11.4qq闪退怎么办 ios11.3qq闪退怎么办 英雄联盟进入游戏界面黑屏怎么办 英雄联盟经常未响应怎么办 英雄联盟总是无响应怎么办 英雄联盟新客户端太卡怎么办 win10英雄联盟fps低怎么办 lol登游戏闪退怎么办 lol读取界面很慢怎么办 玩lol卡死黑屏怎么办 lol黑屏退不出来怎么办 电脑分辨率调高了黑屏怎么办 电脑设置分辨率黑屏了怎么办 分辨率调高了黑屏怎么办 电脑调分辨率黑屏了怎么办 科沃斯cr120遥控器丢了怎么办 买了kl色的钻戒怎么办 qq旋风没有蓝钻怎么办 手机桌面短信图标不见了怎么办 手机桌面qq音乐图标不见了怎么办 电脑显示器图标变大了怎么办 手机卡信号好但是网络不好怎么办 陌陌功能被限制怎么办 陌陌设备封了怎么办 荣耀v8手机开机键不灵怎么办 联通积分换的腾讯会员怎么办 小米6手机变卡了怎么办 微信绑定银行卡次数太多怎么办 银行卡绑定太多微信了怎么办