zoukankan      html  css  js  c++  java
  • Spring事件监听机制

    前言

    Spring中的事件机制其实就是设计模式中的观察者模式,主要由以下角色构成:

    1. 事件
    2. 事件监听器(监听并处理事件)
    3. 事件发布者(发布事件)

    首先看一下监听器和发布者的接口定义

    public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
          void onApplicationEvent(E event);
      }
      
      public interface ApplicationEventPublisher {
    	default void publishEvent(ApplicationEvent event) {
    		publishEvent((Object) event);
    	}
    	void publishEvent(Object event);
    
    }
    

    事件流转流程

    初始化事件广播器

    看一下这个方法AbstractApplicationContext.refresh,在IOC源码解析那篇文章已经把这个方法分析完了,所以直接关注事件广播器和事件发布相关的逻辑即可

    
     public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.
                prepareRefresh();
     
                // Tell the subclass to refresh the internal bean factory.
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
     
                // Prepare the bean factory for use in this context.
                prepareBeanFactory(beanFactory);
     
                try {
                    // Allows post-processing of the bean factory in context subclasses.
                    postProcessBeanFactory(beanFactory);
     
                    // Invoke factory processors registered as beans in the context.
                    invokeBeanFactoryPostProcessors(beanFactory);
     
                    // Register bean processors that intercept bean creation.
                    registerBeanPostProcessors(beanFactory);
     
                    // Initialize message source for this context.
                    initMessageSource();
     
                    // 初始化事件广播器
                    initApplicationEventMulticaster();
     
                    // Initialize other special beans in specific context subclasses.
                    onRefresh();
     
                    // Check for listener beans and register them.
                    registerListeners();
     
                    // Instantiate all remaining (non-lazy-init) singletons.
                    finishBeanFactoryInitialization(beanFactory);
     
                    // 发布事件
                    finishRefresh();
                }
     
                catch (BeansException ex) {
                    logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
     
                    // Destroy already created singletons to avoid dangling resources.
                    destroyBeans();
     
                    // Reset 'active' flag.
                    cancelRefresh(ex);
     
                    // Propagate exception to caller.
                    throw ex;
                }
            }
    }
    
    protected void initApplicationEventMulticaster() {
            ConfigurableListableBeanFactory beanFactory = getBeanFactory();
            if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
                this.applicationEventMulticaster =
                        beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
                if (logger.isDebugEnabled()) {
                    logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
                }
            }
            else {
                this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
                beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
                if (logger.isDebugEnabled()) {
                    logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
                            APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
                            "': using default [" + this.applicationEventMulticaster + "]");
                }
            }
        }
    
    

    可以看到如果没有自定义的事件广播器,默认是使用SimpleApplicationEventMulticaster

    发布事件

    发布事件是在bean的初始化之后的

    
        protected void finishRefresh() {
            // Initialize lifecycle processor for this context.
            initLifecycleProcessor();
     
            // Propagate refresh to lifecycle processor first.
            getLifecycleProcessor().onRefresh();
     
            // 发布事件
            publishEvent(new ContextRefreshedEvent(this));
     
            // Participate in LiveBeansView MBean, if active.
            LiveBeansView.registerApplicationContext(this);
        }
    
    
    public void publishEvent(ApplicationEvent event) {
            Assert.notNull(event, "Event must not be null");
            if (logger.isTraceEnabled()) {
                logger.trace("Publishing event in " + getDisplayName() + ": " + event);
            }
            //1. 获取到事件广播器,发布事件
            getApplicationEventMulticaster().multicastEvent(event);
            //2. 如果存在父容器,父容器也将发布事件
            if (this.parent != null) {
                this.parent.publishEvent(event);
            }
        }
    

    具体的发布逻辑在multicastEvent方法中

    
    public void multicastEvent(final ApplicationEvent event) {
            //遍历执行listener,getApplicationListeners调用AbstractApplicationEventMulticaster父类方法
            for (final ApplicationListener listener : getApplicationListeners(event)) {
                Executor executor = getTaskExecutor();
                if (executor != null) {
                    executor.execute(new Runnable() {
                        @Override
                        public void run() {
                            listener.onApplicationEvent(event);
                        }
                    });
                }
                else {
                    listener.onApplicationEvent(event);
                }
            }
        }
    
    

    可以看到也没啥特殊的,无非就是起个线程池去调用这些监听器的方法

    而监听器的处理就看各个监听器的具体实现了

  • 相关阅读:
    Springboot注解@Scheduled定时任务的使用
    Springboot整合WebSocket和RabbitMQ实现服务器消息推送
    Springboot集成WebSocket实现消息推送功能
    RabbitMq: 主题交换机的使用(Topic Exchange)
    Rabbitmq: @RabbitListener 和 @RabbitHandler 搭配使用
    RabbitMQ开启 mqtt 协议
    @Import的简单使用
    idea快速生成对应数据库的实体类
    HttpClient封装工具类
    TypeScript基本概念
  • 原文地址:https://www.cnblogs.com/zhixiang-org-cn/p/11531633.html
Copyright © 2011-2022 走看看