springboot学习----事件监听

论坛 期权论坛 脚本     
匿名网站用户   2020-12-20 00:57   19   0

起源

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

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP