【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

 

时间: 2024-09-20 00:04:49

【spring源码学习】spring的事件发布监听机制源码解析的相关文章

求vb.net windows service监听端口源码!!

问题描述 求vb.netwindowsservice监听端口源码!!!!!!!!!!!!!!!!!!!! 解决方案 解决方案二:VB.NET端口监听实例ImportsSystem.ComponentModelImportsSystem.DrawingImportsSystem.WinFormsImportsSystem.ThreadingImportsSystem.Net.SocketsPublicClassForm1InheritsSystem.WinForms.FormPrivateoLis

java Gui编程 事件监听机制

1.     GUI编程引言     以前的学习当中,我们都使用的是命令交互方式:        例如:在DOS命令行中通过javac java命令启动程序.     软件的交互的方式:      1. 命令交互方式           图书管理系统     2. 图形交互方式     ava提供了专业的API用于开发图形用户界面     GUI--> Graphic  User   Interface      将要了解GUI API的框架结构,以及GUI组件以及组件之间的关系,容器和布局管理

Android4.0.x Home键事件拦截监听的方法_Android

本文实例讲述了Android4.0.x Home键事件拦截监听的方法.分享给大家供大家参考,具体如下: 在2.3.x 的主要做法如下,具体实现网上有很多文章 @Override public void onAttachedToWindow() { this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD); super.onAttachedToWindow(); } 代码移植到4.0.1后 this.getWindow()

关于JAVA中事件分发和监听机制实现的代码实例

文章标题:关于JAVA中事件分发和监听机制实现的代码实例 文章地址: http://blog.csdn.net/5iasp/article/details/37054171 作者: javaboy2012 Email:yanek@163.com qq:    1046011462     一.场景假设 假设有博客系统中需要实现如下功能: 系统中用户发布文章,修改文章,删除文章时,需要一些相关的操作需要执行. 发布文章后,给好友发送邮件通知,给用户加积分,对文章做全文索引. 修改文章后,给好友发送

Android4.0.x Home键事件拦截监听的方法

本文实例讲述了Android4.0.x Home键事件拦截监听的方法.分享给大家供大家参考,具体如下: 在2.3.x 的主要做法如下,具体实现网上有很多文章 @Override public void onAttachedToWindow() { this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD); super.onAttachedToWindow(); } 代码移植到4.0.1后 this.getWindow()

Android开发之PullToRefresh的Click点击事件的监听实现长按删除Item

本文为原创博客,出自http://blog.csdn.net/minimicall 到今天为止,搜芽的卖家版本应该来说已经基本完成,攻坚克难的一路过来.速度也控制的比较好. 项目过程进度 从任务分配量上来看,基本还是我个人英雄主义.接下来这样不行.但暂时也没办法,师弟还需要一个学习的过程.智质不错,而且态度端正.相信搜芽买家,他就可以承担更多的开发任务了. 接下来进入正题,说我们的PullToRefresh的点击事件.其实,我是想做长按进入删除的. 见效果图.当然这个是我做出来之后的了,但做出来

.NET事件监听机制的局限与扩展分析_实用技巧

本文实例分析了.NET事件监听机制的局限与扩展.分享给大家供大家参考.具体分析如下: .NET中把"事件"看作一个基本的编程概念,并提供了非常优美的语法支持,对比如下C#和Java代码可以看出两种语言设计思想之间的差异. 复制代码 代码如下: // C# someButton.Click += OnSomeButtonClick; 复制代码 代码如下: // Java someButton.addActionListener(     new ActionListener(){    

JAVA之旅(三十一)——JAVA的图形化界面,GUI布局,Frame,GUI事件监听机制,Action事件,鼠标事件

JAVA之旅(三十一)--JAVA的图形化界面,GUI布局,Frame,GUI事件监听机制,Action事件,鼠标事件 有段时间没有更新JAVA了,我们今天来说一下JAVA中的图形化界面,也就是GUI 一.GUI的概述 GUI全称叫做Graphical User Intergace(图形用户接口),用图形的方式,来显示计算机操作的界面,这样更加方便直观,与用户交互 说道交互,其实系统跟用户有两种交互,一种是GUI,一种叫做CLI,也就是命令行,全称叫做Command User Intergace

nodejs事件的监听与触发的理解分析

 这篇文章主要介绍了nodejs事件的监听与触发的理解分析,以实例形式对比分析了nodejs与jQuery关于事件监听的实用技巧,有助于加深对nodejs的理解,需要的朋友可以参考下     本文实例分析了nodejs事件的监听与触发.分享给大家供大家参考.具体分析如下: 关于nodejs的事件驱动,看了<nodejs深入浅出>还是没看明白(可能写的有点深,或者自己理解能力不够好),今日在图灵社区看到一篇关于nodejs事件的监听与触发,由于给出的例子比较多人,很容易理解,所以也大致明白了no