当前位置: 代码网 > it编程>编程语言>Java > Spring事件监听机制详解:如何实现事件发布与监听

Spring事件监听机制详解:如何实现事件发布与监听

2026年08月16日 Java 我要评论
众所周知,spring framework在 beanfactory的基础容器之上扩展为了applicationcontext上下文。 applicationcontext处理包含了beanfacto

众所周知,spring framework在 beanfactory的基础容器之上扩展为了applicationcontext上下文。 applicationcontext处理包含了beanfactory的全部基础功能之外,还额外提供了大量的扩展功能。

今天我们就来看看 扩展的 事件监听接口

概述

我们都知道 实现事件监听机制至少四个组成部分:

  • 事件
  • 事件生产者
  • 事件消费者
  • 控制器 (管理生产者、消费者和事件之间的注册监听关系)

在spring中,事件监听机制主要实现是通过事件、事件监听器、事件发布者和事件广播器来实现。

applicationevent ------ 事件

public abstract class applicationcontextevent extends applicationevent {

	/**
	 * create a new contextstartedevent.
	 * @param source the {@code applicationcontext} that the event is raised for
	 * (must not be {@code null})
	 */
	public applicationcontextevent(applicationcontext source) {
		super(source);
	}

	/**
	 * get the {@code applicationcontext} that the event was raised for.
	 */
	public final applicationcontext getapplicationcontext() {
		return (applicationcontext) getsource();
	}

}

抽象父类applicationevent,它的子抽象类applicationcontextevent 包含有当前applicationcontext的引用,这样就可以确认每个事件是从哪一个spring容器中发生的。

applicationlistener ------ 事件监听器

顶级接口applicationlistener,只有一个void onapplicationevent(e event); ,当该监听器所监听的事件发生时,就会执行该方法

applicationeventpublisher ------ 事件发布者

顶级接口applicationeventpublisher,只有一个方法 void publishevent(object event); ,调用该方法就可以发生spring中的事件

applicationeventmulticaster ------ 事件广播器

spring中的事件核心控制器叫做事件广播器,两个作用

将事件监听器注册到广播器中

这样广播器就知道了每个事件监听器分别监听什么事件,且知道了每个事件对应哪些事件监听器在监听。

将事件广播给事件监听器

当有事件发生时,需要通过广播器来广播给所有的事件监听器,因为生产者只需要关心事件的生产,而不需要关心该事件都被哪些监听器消费。

spring主要的内置事件

contextrefreshedevent

applicationcontext 被初始化或刷新时,该事件被发布。

也可以在configurableapplicationcontext接口中使用 refresh()方法来发生。

此处的初始化是指:所有的bean被成功装载,后处理bean被检测并激活,所有singleton bean 被预实例化,applicationcontext容器已就绪可用。

contextstartedevent

当使用 configurableapplicationcontext 接口中的 start() 方法启动 applicationcontext时,该事件被发布。

可以在接受到这个事件后重启任何停止的应用程序。

contextstoppedevent

当使用 configurableapplicationcontext接口中的 stop()停止applicationcontext 时,发布这个事件。

可以在接受到这个事件后做必要的清理的工作

contextclosedevent

当使用 configurableapplicationcontext接口中的 close()方法关闭 applicationcontext 时,该事件被发布。

一个已关闭的上下文到达生命周期末端;它不能被刷新或重启

requesthandledevent

这是一个 web-specific 事件,告诉所有 bean http 请求已经被服务。只能应用于使用dispatcherservlet的web应用。

在使用spring作为前端的mvc控制器时,当spring处理用户请求结束后,系统会自动触发该事件

org.springframework.context.applicationlistener

@functionalinterface
public interface applicationlistener<e extends applicationevent> extends eventlistener {

	/**
	 * handle an application event.
	 * @param event the event to respond to
	 */
	void onapplicationevent(e event);


	/**
	 * create a new {@code applicationlistener} for the given payload consumer.
	 * @param consumer the event payload consumer
	 * @param <t> the type of the event payload
	 * @return a corresponding {@code applicationlistener} instance
	 * @since 5.3
	 * @see payloadapplicationevent
	 */
	static <t> applicationlistener<payloadapplicationevent<t>> forpayload(consumer<t> consumer) {
		return event -> consumer.accept(event.getpayload());
	}

}

applicationlistener可以监听某个事件的event,触发时机可以穿插在业务方法执行过程中,用户可以自定义某个业务事件。

源码分析

首先看看spring在初始化的时候,有两个核心步骤和事件监听器有关,一个是初始化事件广播器,一个是注册所有的事件监听器

org.springframework.context.support.abstractapplicationcontext#refresh
@override
	public void refresh() throws beansexception, illegalstateexception {
		synchronized (this.startupshutdownmonitor) {
			 		
				// initialize event multicaster for this context.
				initapplicationeventmulticaster();
 

				// check for listener beans and register them.
				registerlisteners();

				 
		 
	}

初始化事件广播器

	/** spring容器的事件广播器对象*/
    private applicationeventmulticaster applicationeventmulticaster;

    /** 事件广播器对应的beanname*/
    public static final string application_event_multicaster_bean_name = "applicationeventmulticaster";

    /** 初始化事件广播器*/
    protected void initapplicationeventmulticaster() {
        //1.获取spring容器beanfactory对象
        configurablelistablebeanfactory beanfactory = getbeanfactory();
        //2.从beanfactory获取事件广播器的bean,如果存在说明是用户自定义的事件广播器
        if (beanfactory.containslocalbean(application_event_multicaster_bean_name)) {
            //2.1.给容器的事件广播器赋值
            this.applicationeventmulticaster =
                    beanfactory.getbean(application_event_multicaster_bean_name, applicationeventmulticaster.class);
            if (logger.istraceenabled()) {
                logger.trace("using applicationeventmulticaster [" + this.applicationeventmulticaster + "]");
            }
        }
        else {
            //3.如果没有自定义的,则初始化默认的事件广播器simpleapplicationeventmulticaster对象
            this.applicationeventmulticaster = new simpleapplicationeventmulticaster(beanfactory);
            //4.注册该bean
            beanfactory.registersingleton(application_event_multicaster_bean_name, this.applicationeventmulticaster);
            if (logger.istraceenabled()) {
                logger.trace("no '" + application_event_multicaster_bean_name + "' bean, using " +
                        "[" + this.applicationeventmulticaster.getclass().getsimplename() + "]");
            }
        }
    }

如果beanfactory中存在用于自定义的就使用自定义的,如果没有自定义的就创建新的默认的事件广播器simpleapplicationeventmulticaster对象,然后赋值给applicationeventmulticaster对象。

注册事件监听器

	/** 注册事件监听器*/
    protected void registerlisteners() {
        //1.遍历将通过编码方式创建的事件监听器加入到事件广播器中
        for (applicationlistener<?> listener : getapplicationlisteners()) {
            //2.获取到当前事件广播器,添加事件监听器
            getapplicationeventmulticaster().addapplicationlistener(listener);
        }

        //3.从beanfactory中获取所有实现了applicationlistener接口的bean,遍历加入到事件广播器中
        string[] listenerbeannames = getbeannamesfortype(applicationlistener.class, true, false);
        for (string listenerbeanname : listenerbeannames) {
            getapplicationeventmulticaster().addapplicationlistenerbean(listenerbeanname);
        }

        //3.获取需要提前发布的事件
        set<applicationevent> earlyeventstoprocess = this.earlyapplicationevents;
        this.earlyapplicationevents = null;
        if (earlyeventstoprocess != null) {
            for (applicationevent earlyevent : earlyeventstoprocess) {
                //5.遍历将提前发布的事件广播出去
                getapplicationeventmulticaster().multicastevent(earlyevent);
            }
        }

从容器中找到所有的事件监听器,然后调用事件广播器的addapplicationlistener方法将事件监听器添加到事件广播器中。

事件的发布和消费

事件的发布是通过applicationeventpublisher的实现类实现的publishevent方法实现的,applicationcontext就实现了该接口,所以使用spring时就可以直接使用applicationcontext实例来调用publishevent方法来发布事件

	/** 发布事件
     * @param event:事件对象
     *  */
    @override
    public void publishevent(object event) {
        publishevent(event, null);
    }

    /** 发布事件
     * @param event:事件对象
     * @param eventtype:事件类型
     * */
    protected void publishevent(object event, @nullable resolvabletype eventtype) {
        assert.notnull(event, "event must not be null");

        /** 1.将发布的事件封装成applicationevent对象(因为传入的参数是object类型,有可能没有继承applicationevent) */
        applicationevent applicationevent;
        if (event instanceof applicationevent) {
            applicationevent = (applicationevent) event;
        }
        else {
            applicationevent = new payloadapplicationevent<>(this, event);
            if (eventtype == null) {
                eventtype = ((payloadapplicationevent<?>) applicationevent).getresolvabletype();
            }
        }

        if (this.earlyapplicationevents != null) {
            /** 2.1.如果需要提前发布的事件还没有发布完,则不是立即发布,而是将事件加入到待发布集合中*/
            this.earlyapplicationevents.add(applicationevent);
        }
        else {
            /** 2.2.获取当前的事件广播器,调用multicasterevent方法广播事件*/
            getapplicationeventmulticaster().multicastevent(applicationevent, eventtype);
        }

        /** 3.如果当前applicationcontext有父类,则再调用父类的publishevent方法*/
        if (this.parent != null) {
            if (this.parent instanceof abstractapplicationcontext) {
                ((abstractapplicationcontext) this.parent).publishevent(event, eventtype);
            }
            else {
                this.parent.publishevent(event);
            }
        }
    }

首先是将发布的事件转化成applicationevent对象,然后获取到事件广播器,调用事件广播器的multicastevent方法来广播事件,所以核心逻辑又回到了事件广播器那里

	/** 广播事件
     * @param event:事件
     * @param eventtype:事件类型
     * */
    @override
    public void multicastevent(final applicationevent event, @nullable resolvabletype eventtype) {
        resolvabletype type = (eventtype != null ? eventtype : resolvedefaulteventtype(event));
        executor executor = gettaskexecutor(); // (如果有executor,则广播事件就是通过异步来处理的)
        /**
         * 1.根据事件和类型调用getapplicationlisteners方法获取所有监听该事件的监听器
         * */
        for (applicationlistener<?> listener : getapplicationlisteners(event, type)) {
            if (executor != null) {
                /** 2. 异步遍历执行invokelistener方法来唤醒监听器处理事件 */
                executor.execute(() -> invokelistener(listener, event));
            }
            else {
                invokelistener(listener, event);
            }
        }
    }

这里主要有两个核心步骤,

  • 首先是根据事件和类型找到监听了该事件的所有事件监听器
  • 然后遍历来执行监听器的处理逻辑.另外如果配置了执行器executor,就会通过executor来异步发布事件给监听器

根据事件获取事件监听器

protected collection<applicationlistener<?>> getapplicationlisteners(
            applicationevent event, resolvabletype eventtype) {

        object source = event.getsource();
        class<?> sourcetype = (source != null ? source.getclass() : null);
        listenercachekey cachekey = new listenercachekey(eventtype, sourcetype);

        // quick check for existing entry on concurrenthashmap...
        listenerretriever retriever = this.retrievercache.get(cachekey);
        if (retriever != null) {
            return retriever.getapplicationlisteners();
        }

        if (this.beanclassloader == null ||
                (classutils.iscachesafe(event.getclass(), this.beanclassloader) &&
                        (sourcetype == null || classutils.iscachesafe(sourcetype, this.beanclassloader)))) {
            // fully synchronized building and caching of a listenerretriever
            synchronized (this.retrievalmutex) {
                retriever = this.retrievercache.get(cachekey);
                if (retriever != null) {
                    return retriever.getapplicationlisteners();
                }
                retriever = new listenerretriever(true);
                collection<applicationlistener<?>> listeners =
                        retrieveapplicationlisteners(eventtype, sourcetype, retriever);
                this.retrievercache.put(cachekey, retriever);
                return listeners;
            }
        }
        else {
            // no listenerretriever caching -> no synchronization necessary
            return retrieveapplicationlisteners(eventtype, sourcetype, null);
        }
    }

核心方法是retrieveapplicationlisteners(eventtype, sourcetype, retriever)方法,源码如下:

private collection<applicationlistener<?>> retrieveapplicationlisteners(
            resolvabletype eventtype, @nullable class<?> sourcetype, @nullable listenerretriever retriever) {

        list<applicationlistener<?>> alllisteners = new arraylist<>();
        set<applicationlistener<?>> listeners;
        set<string> listenerbeans;
         /** 初始化所有事件监听器,存入集合中*/
        synchronized (this.retrievalmutex) {              
            listeners = new linkedhashset<>(this.defaultretriever.applicationlisteners);
            listenerbeans = new linkedhashset<>(this.defaultretriever.applicationlistenerbeans);
        }

        // add programmatically registered listeners, including ones coming
        // 遍历所有监听器,调用supportsevent判断是否监听该事件
        for (applicationlistener<?> listener : listeners) {
            if (supportsevent(listener, eventtype, sourcetype)) {
                if (retriever != null) {
                    retriever.applicationlisteners.add(listener);
                }                   /** 如果监听器监听当前事件,则加入到监听器集合中*/
                alllisteners.add(listener);
            }
        }

        // add listeners by bean name, potentially overlapping with programmatically
        // registered listeners above - but here potentially with additional metadata.
        if (!listenerbeans.isempty()) {
            configurablebeanfactory beanfactory = getbeanfactory();
                       //
            for (string listenerbeanname : listenerbeans) {
                try {
                    if (supportsevent(beanfactory, listenerbeanname, eventtype)) {
                        applicationlistener<?> listener =
                                beanfactory.getbean(listenerbeanname, applicationlistener.class);
                        if (!alllisteners.contains(listener) && supportsevent(listener, eventtype, sourcetype)) {
                            if (retriever != null) {
                                if (beanfactory.issingleton(listenerbeanname)) {
                                    retriever.applicationlisteners.add(listener);
                                }
                                else {
                                    retriever.applicationlistenerbeans.add(listenerbeanname);
                                }
                            }
                            alllisteners.add(listener);
                        }
                    }
                    else {
                        // remove non-matching listeners that originally came from
                        // applicationlistenerdetector, possibly ruled out by additional
                        // beandefinition metadata (e.g. factory method generics) above.
                        object listener = beanfactory.getsingleton(listenerbeanname);
                        if (retriever != null) {
                            retriever.applicationlisteners.remove(listener);
                        }
                        alllisteners.remove(listener);
                    }
                }
                catch (nosuchbeandefinitionexception ex) {
                    // singleton listener instance (without backing bean definition) disappeared -
                    // probably in the middle of the destruction phase
                }
            }
        }

        /** 将所有监听器根据order进行排序*/
        annotationawareordercomparator.sort(alllisteners);
        if (retriever != null && retriever.applicationlistenerbeans.isempty()) {
            retriever.applicationlisteners.clear();
            retriever.applicationlisteners.addall(alllisteners);
        }
        return alllisteners;
    }

核心步骤:

  • 1:获取事件广播器中所有的事件监听器
  • 2:遍历事件监听器,判断该监听器是否监听当前事件
  • 3:将所有监听当前事件的监听器进行排序

第二步判断监听器是否监听事件的判断,主要是通过反射获取该监听器实现的接口泛型类,如果包含当前事件的类则表示监听,否则就表示不监听

唤醒监听器处理事件

protected void invokelistener(applicationlistener<?> listener, applicationevent event) {
        errorhandler errorhandler = geterrorhandler();
        if (errorhandler != null) {
            try {
                /** 调用doinvokelistener方法*/
                doinvokelistener(listener, event);
            }
            catch (throwable err) {
                errorhandler.handleerror(err);
            }
        }
        else {
            /** 调用doinvokelistener方法*/
            doinvokelistener(listener, event);
        }
    }

继续

private void doinvokelistener(applicationlistener listener, applicationevent event) {
        try {
		    /** 直接调用applicationlistener的onapplicationevent(event)方法*/
            listener.onapplicationevent(event);
        }
        catch (classcastexception ex) {
              
        }
    }

直接调用监听器的onapplicationevent方法

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com