zoukankan      html  css  js  c++  java
  • 【spring源码学习】spring的事件发布监听机制源码解析

    【一】相关源代码类

    (1)spring的事件发布监听机制的核心管理类:org.springframework.context.event.SimpleApplicationEventMulticaster.

      =>该类的初始化是放在项目加载时,在ioc容器xml配置文件解析加载完毕后,注册bean创建前后置处理实现类(BeanPostProcessor 接口实现),beanFactory配置处理(BeanFactoryPostProcessor接口实现)后,初始化该事件发布监听机制的核心类。

    public void refresh() throws BeansException, IllegalStateException {
            synchronized (this.startupShutdownMonitor) {
                // Prepare this context for refreshing.
                prepareRefresh();
    
                // 解析xml配置文件
                ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
                // Prepare the bean factory for use in this context.
                prepareBeanFactory(beanFactory);
    
                try {
                    // 注册未来bean实例化的前后置处理的PostProcessor接口实现
                    postProcessBeanFactory(beanFactory);
    
                    //执行所有实现BeanFactoryPostProcessor接口实现,对beanFactory进行处理
                    invokeBeanFactoryPostProcessors(beanFactory);
    
                    //  注册未来bean实例化的前后置处理的PostProcessor接口实现
                    registerBeanPostProcessors(beanFactory);
    
                    // 注册未来bean实例化的前后置处理的PostProcessor接口实现
                    initMessageSource();
    
                    // 实例化spring事件发布监听机制的核心类,SimpleApplicationEventMulticaster
                    initApplicationEventMulticaster();
    
                    // Initialize other special beans in specific context subclasses.
                    onRefresh();
    
                    // 注册事件监听器
                    registerListeners();
    
                    // 实例化非懒加载的bean,完成ioc容器中bean的实例化和反转依赖,并在内部实现动态代理相关的操作
                    finishBeanFactoryInitialization(beanFactory);
    
                    // Last step: publish corresponding event.
                    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;
                }
            }
        }
    View Code

    (2)spring的事件发布监听机制的监听器类的接口:org.springframework.context.ApplicationListener<E extends ApplicationEvent>

      =>监听器的定义必须实现该接口。

      =>所监听的事件也必须继承org.springframework.context.ApplicationEvent的抽象类

      =>在初始化管理类后,会注册监听器。会从beanFactory里得到所有实现ApplicationListener接口的bean的名字,并注册到ListenerRetriever的属性applicationListenerBeans集合中。

    (3)spring的事件发布监听机制的事件的基础类:org.springframework.context.ApplicationEvent

      =>事件的事件类必须继承该基类

      =>定义监听器的同时,必须定义相关的事件类。

    (4)spring的事件发布监听机制的存储事件监听的类:org.springframework.context.event.AbstractApplicationEventMulticaster.ListenerRetriever

        =>该类内部存储了一个n个事件对应的多个监听器

        =>属性Set<ApplicationListener<?>> applicationListeners  存储的是事件监听器的实例

        =>属性Set<String> applicationListenerBeans  存储的事件监听器在ioc容器中的beanNames



    (5)spring的事件发布监听机制的存储事件体的类:org.springframework.context.event.AbstractApplicationEventMulticaster.ListenerCacheKey

        =>一个事件体的class类型+事件源(事件体内存储的数据)的class类型决定由那些监听监听器处理该事件

        =>属性Class<?> eventType 存储的事件体的class类型

        =>属性Class<?> sourceType 存储的事件源的class类型(事件体内数据)

    【二】设计思想

    (1)通过事件体,拿到事件类的cls1类型,和事件源(事件体内部存储的数据类)的cls类型

    (2)然后在IOC容器中所有实现ApplicationListener接口的事件监听器中进行匹配。找到所有适合该事件的事件监听器集合。将事件监听集合形成ListenerRetriever对象。

      =>从IOC容器中的一个个事件监听器实现类的范型填充类的类型(也就是事件体的 类型)cls2

      =>Listener可能是代理对象(因为@Async注解),Listenner的ioc在实例化阶段,会被spring创建成代理对象。spring内部也会做处理,得到代理对象代理的targetClass,也就是Listenner的真实类型。

      =>看当前事件体的类型cls1是否是事件监听器的范型填充类的类型cls2的子类或本身。如果是,则表示这个事件监听器匹配该事件。

    (3)将该事件体,的事件类的cls1类型+事件源的cls类型。形成ListenerCacheKey对象,以此为key,以事件监听集合ListenerRetriever对象作为value,存储在AbstractApplicationEventMulticaster类中private final Map<ListenerCacheKey, ListenerRetriever> retrieverCache = new ConcurrentHashMap<ListenerCacheKey, ListenerRetriever>(64);属性中作为cache,方便下次匹配,不再从ioc容器中重新匹配。

    【三】事件缓冲,扩展。hasMap中以对象作为key。需要重写hasCode方法,equals方法

    private static class ListenerCacheKey {
    
            private final Class<?> eventType;
    
            private final Class<?> sourceType;
    
            public ListenerCacheKey(Class<?> eventType, Class<?> sourceType) {
                this.eventType = eventType;
                this.sourceType = sourceType;
            }
    
            @Override
            public boolean equals(Object other) {
                if (this == other) {
                    return true;
                }
                ListenerCacheKey otherKey = (ListenerCacheKey) other;
                return ObjectUtils.nullSafeEquals(this.eventType, otherKey.eventType) &&
                        ObjectUtils.nullSafeEquals(this.sourceType, otherKey.sourceType);
            }
    
            @Override
            public int hashCode() {
                return ObjectUtils.nullSafeHashCode(this.eventType) * 29 + ObjectUtils.nullSafeHashCode(this.sourceType);
            }
        }
    View Code
  • 相关阅读:
    C#中的静态
    C#类的使用
    C#接口实现多态
    C#---->类和接口
    winform项目导入数据
    kms访问数据库的方式(该篇只是作为个人笔记,不具有任何公共参考意图)
    win7下安装docker toolbox
    JabRef:将bibtex格式的参考文献导入EndNote的转换软件
    RabbitMQ安装以及简单操作应用(针对Windows和C#)
    C# Task和异步方法
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/7239473.html
Copyright © 2011-2022 走看看