zoukankan      html  css  js  c++  java
  • Spring源码解析-事件

    Spring事件的组件

    主要是3个组件:

    1.ApplicationEvent   事件

    2.ApplicationListener 监听器,对事件进行监听

    3.ApplicationEventMulticaster 事件广播器,将publish的事件广播给所有的监听器。

    事件

    ContextRefreshedEvent :当ApplicationContext初始化或者刷新,将会发布,例如使用ConfigurableApplicationContext接口调用refresh方法,初始化意味着加载所有的bean,同时

    ApplicationContext是支持热刷新。

    ContextStartedEvent:当ApplicationContext启动的时候,将会调用start方法,发布此事件。

    ContextStoppedEvent:当容器停止的时候,发布事件。

    ContextClosedEvent:当容器关闭的时候,发布事件。

    RequestHandledEvent:http请求完成后,发布事件。

    监听器

    ApplicationListener:ApplicationContext容器内部自定义事件监听器接口,继承自java.util.EventListener,ApplicationContext容器在启动时,会自动识别并加载EventListener类型bean的定义,一旦容器事件发布,将会通知注册到容器的监听器。

                                                                         

    public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    
    	/**
    	 * Handle an application event.
    	 * @param event the event to respond to
    	 */
    	void onApplicationEvent(E event);
    
    }
    

    发布事件者

    ApplicationEventPublisher和ApplicationEventMulticaster
    ApplicationEventPublisher:是一个封装事件发布接口,作为ApplicationContext父类接口。
    ApplicationEventMulticaster:管理ApplicationListener对象,并且发布它们。

                                                   

    ApplicationContext继承ApplicationEventPublisher而担当者事件发布的角色,而ApplicationContext并没有进行事件的发布,而是交给了AbstractApplicationEventMulticaster来实现事件监听器的管理。

    简单实例

    模拟人民银行利息调整,通知到其他银行的事件。

    利息事件

    package org.lzyer.test;
    
    import org.springframework.context.ApplicationEvent;
    
    /**
     * Created by Administrator on 2017/10/23.
     */
    public class ExRateChangeEvent extends ApplicationEvent {
        /**
         * Create a new ApplicationEvent.
         *
         * @param source the component that published the event (never {@code null})
         */
        public ExRateChangeEvent(Object source) {
            super(source);
        }
    }
    

    农业银行监听器

    package org.lzyer.test;
    
    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationListener;
    import org.springframework.stereotype.Component;
    
    /**
     * Created by Administrator on 2017/10/23.
     */
    @Component
    public class ABCListener implements ApplicationListener<ApplicationEvent> {
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            if(event instanceof  ExRateChangeEvent){
                System.out.println("农业银行收到->"+event.getSource());
            }
        }
    }
    

    工商银行监听器

    package org.lzyer.test;
    
    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationListener;
    import org.springframework.stereotype.Component;
    
    /**
     * Created by Administrator on 2017/10/23.
     */
    @Component
    public class ICBCListener implements ApplicationListener<ApplicationEvent> {
    
        @Override
        public void onApplicationEvent(ApplicationEvent event) {
            if(event instanceof  ExRateChangeEvent){
                System.out.println("工商银行收到->"+event.getSource());
            }
        }
    }
    

    spring-beans.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="org.lzyer.test"></context:component-scan>
    </beans>
    

    测试代码

    @Test
        public void testPublishEvent(){
            ApplicationContext context = new ClassPathXmlApplicationContext("spring/spring-beans.xml");
            context.publishEvent(new ExRateChangeEvent("利息上调"));
        }

    结果:

    农业银行收到->利息上调
    工商银行收到:->利息上调

    事件原理流程

    spring容器初始化调用的refresh方法

    AbstractApplicationContext@refresh

    @Override
    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    			//省略
    
    			try {
    				//省略
    
    				// 初始化广播事件
    				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);
    
    				// Last step: publish corresponding event.
    				finishRefresh();
    			}
    
    			catch (BeansException ex) {
    				//省略
    			}
    		}
    	}            
    

    initApplicationEventMulticaster()注册广播事件

    protected void initApplicationEventMulticaster() {
    //获取beanFactory 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 + "]"); } } }
    AbstractApplicationEventMulticaster类中的属性

    registerListeners方法
    /**
    	 * Add beans that implement ApplicationListener as listeners.
    	 * Doesn't affect other listeners, which can be added without being beans.
    	 */
    	protected void registerListeners() {
    		// Register statically specified listeners first.
    		for (ApplicationListener<?> listener : getApplicationListeners()) {
    			getApplicationEventMulticaster().addApplicationListener(listener);
    		}
    		// Do not initialize FactoryBeans here: We need to leave all regular beans
    		// uninitialized to let post-processors apply to them!
    		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    		for (String lisName : listenerBeanNames) {
    			getApplicationEventMulticaster().addApplicationListenerBean(lisName);
    		}
    	}
    

    在refresh最后的一个方法,中发布刷新事件。

    finishRefresh
    protected void finishRefresh() {
    		// Initialize lifecycle processor for this context.
    		initLifecycleProcessor();
    
    		// Propagate refresh to lifecycle processor first.
    		getLifecycleProcessor().onRefresh();
    
    		// Publish the final event.发布刷新事件
    		publishEvent(new ContextRefreshedEvent(this));
    
    		// Participate in LiveBeansView MBean, if active.
    		LiveBeansView.registerApplicationContext(this);
    	}

    事件整体结构图

    最后走一波debug

     

    参考资料
    http://www.jianshu.com/p/bc1055b065ce
    http://liuxiamai.iteye.com/blog/2322197
    http://jinnianshilongnian.iteye.com/blog/1902886



      




  • 相关阅读:
    DataGrip中执行ORACL语句块进行代码测试
    ORACLE存储过程中使用SELECT INOT语句避免NO_DATA_FOUND的方法
    Pandas和numpy如何显示全部数据
    qrcodejs2+html2canvas生产二维码海报vue
    SQL多表查询
    行者app定位不准的问题分析
    Gdb printer打印STL
    Linux中的文件和目录结构详解
    Linux 文件的路径以及管理
    linux创建ftp服务
  • 原文地址:https://www.cnblogs.com/lzeffort/p/7726602.html
Copyright © 2011-2022 走看看