当前位置: 代码网 > it编程>编程语言>Java > 使用Spring注解@EventListener实现监听原理

使用Spring注解@EventListener实现监听原理

2024年08月13日 Java 我要评论
@eventlistener使用方式package com.cyl.listener;import org.springframework.context.applicationevent;impor

@eventlistener使用方式

package com.cyl.listener;

import org.springframework.context.applicationevent;
import org.springframework.context.payloadapplicationevent;
import org.springframework.context.event.eventlistener;
import org.springframework.stereotype.component;

@component
public class cylorderseclistener {

	@eventlistener
	public void listen(applicationevent event) {
		system.out.println(event);
	}
}

@eventlistener实现原理

主要通过eventlistenermethodprocessor和defaulteventlistenerfactory这两个类实现。

  • eventlistenermethodprocessor的作用是识别所有使用eventlistener注解的方法
  • defaulteventlistenerfactory将eventlistenermethodprocessor识别出的方法封装成为监听器类

以代码new annotationconfigapplicationcontext为入口调试代码去讲解eventlistenermethodprocessor和defaulteventlistenerfactory如何去生效的

package com.cyl;

import org.springframework.context.annotation.annotationconfigapplicationcontext;

public class test {

	public static void main(string[] args) {
		// 创建一个spring容器
		annotationconfigapplicationcontext context = new annotationconfigapplicationcontext();
		context.register(appconfig.class);
		context.refresh();
    }
}

1.引入时机-获取bean定义

eventlistenermethodprocessor和defaulteventlistenerfactory的bean定义信息在容器初始化最开始阶段,defaultlistablebeanfactory实例化后,被注册到defaultlistablebeanfactory的beandefinitionmap中。

执行new annotationconfigapplicationcontext,会优先执行父类 genericapplicationcontex构造方法,实例化一个bean工厂

genericapplicationcontext执行完后,会实例化annotatedbeandefinitionreader,可以理解为容器内一个bean定义阅读器,负责将bean定义注册到bean工厂中。

实例化annotatedbeandefinitionreader会注册一些bean定义到bean工厂中,其中就包括了eventlistenermethodprocessor和defaulteventlistenerfactory。

2.实例化时机-new对象

只引入了bean定义,还未真正对bean进行实例化,实例化步骤是在spring执行refresh时

走到方法内,会调用

org.springframework.context.support.postprocessorregistrationdelegate#invokebeanfactorypostprocessors(org.springframework.beans.factory.config.configurablelistablebeanfactory, java.util.list<org.springframework.beans.factory.config.beanfactorypostprocessor>)

关注代码184行,获取普通beanfactorypostprocessor类,而eventlistenermethodprocessor实现了beanfactorypostprocessor,此处打断点也会获取该类名

由于eventlistenermethodprocessor没有实现priorityordered或者ordered接口,所以就被放入了nonorderedpostprocessornames中最后被执行

当执行beanfactory.getbean(ppname, beanfactorypostprocessor.class)会进行实例化走到eventlistenermethodprocessor的构造函数中

到此eventlistenermethodprocessor实例化好了,代码继续执行

会执行到eventlistenermethodprocessor.postprocessbeanfactory(),在这里实例化defaulteventlistenerfactory

3.作用时机->将加了eventlistener注解的方法识别出来

并封装为监听器,加载spring容器中

当执行

org.springframework.beans.factory.support.defaultlistablebeanfactory#preinstantiatesingletons

初始化后,

因eventlistenermethodprocessor实现了smartinitializingsingleton,

而所有实现smartinitializingsingleton类对象都需要在所有对象初始化后再执行aftersingletonsinstantiated

即:

org.springframework.beans.factory.support.defaultlistablebeanfactory#preinstantiatesingletons
@override
	public void preinstantiatesingletons() throws beansexception {
		if (logger.istraceenabled()) {
			logger.trace("pre-instantiating singletons in " + this);
		}

		// iterate over a copy to allow for init methods which in turn register new bean definitions.
		// while this may not be part of the regular factory bootstrap, it does otherwise work fine.
		list<string> beannames = new arraylist<>(this.beandefinitionnames);

		// trigger initialization of all non-lazy singleton beans...
		for (string beanname : beannames) {
			// 获取合并后的beandefinition
			rootbeandefinition bd = getmergedlocalbeandefinition(beanname);

			if (!bd.isabstract() && bd.issingleton() && !bd.islazyinit()) {
				if (isfactorybean(beanname)) {
					// 获取factorybean对象
					object bean = getbean(factory_bean_prefix + beanname);
					if (bean instanceof factorybean) {
						factorybean<?> factory = (factorybean<?>) bean;
						boolean iseagerinit;
						if (system.getsecuritymanager() != null && factory instanceof smartfactorybean) {
							iseagerinit = accesscontroller.doprivileged(
									(privilegedaction<boolean>) ((smartfactorybean<?>) factory)::iseagerinit,
									getaccesscontrolcontext());
						}
						else {
							iseagerinit = (factory instanceof smartfactorybean &&
									((smartfactorybean<?>) factory).iseagerinit());
						}
						if (iseagerinit) {
							// 创建真正的bean对象(getobject()返回的对象)
							getbean(beanname);
						}
					}
				}
				else {
					// 创建bean对象
					getbean(beanname);
				}
			}
		}

		// 所有的非懒加载单例bean都创建完了后
		// trigger post-initialization callback for all applicable beans...
		for (string beanname : beannames) {
			object singletoninstance = getsingleton(beanname);
			if (singletoninstance instanceof smartinitializingsingleton) {
				startupstep smartinitialize = this.getapplicationstartup().start("spring.beans.smart-initialize")
						.tag("beanname", beanname);
				smartinitializingsingleton smartsingleton = (smartinitializingsingleton) singletoninstance;
				if (system.getsecuritymanager() != null) {
					accesscontroller.doprivileged((privilegedaction<object>) () -> {
						smartsingleton.aftersingletonsinstantiated();
						return null;
					}, getaccesscontrolcontext());
				}
				else {
					smartsingleton.aftersingletonsinstantiated();
				}
				smartinitialize.end();
			}
		}
	}

当执行smartsingleton.aftersingletonsinstantiated();就会调到

org.springframework.context.event.eventlistenermethodprocessor#aftersingletonsinstantiated

eventlistenermethodprocessor真正的处理逻辑来了,主要看第38行关键方法

@override
	public void aftersingletonsinstantiated() {
		configurablelistablebeanfactory beanfactory = this.beanfactory;
		assert.state(this.beanfactory != null, "no configurablelistablebeanfactory set");
		string[] beannames = beanfactory.getbeannamesfortype(object.class);
		for (string beanname : beannames) {
			if (!scopedproxyutils.isscopedtarget(beanname)) {

				// 拿到当前bean对象的类型
				class<?> type = null;
				try {
					type = autoproxyutils.determinetargetclass(beanfactory, beanname);
				}
				catch (throwable ex) {
					// an unresolvable bean type, probably from a lazy bean - let's ignore it.
					if (logger.isdebugenabled()) {
						logger.debug("could not resolve target class for bean with name '" + beanname + "'", ex);
					}
				}
				if (type != null) {
					if (scopedobject.class.isassignablefrom(type)) {
						try {
							class<?> targetclass = autoproxyutils.determinetargetclass(
									beanfactory, scopedproxyutils.gettargetbeanname(beanname));
							if (targetclass != null) {
								type = targetclass;
							}
						}
						catch (throwable ex) {
							// an invalid scoped proxy arrangement - let's ignore it.
							if (logger.isdebugenabled()) {
								logger.debug("could not resolve target bean for scoped proxy '" + beanname + "'", ex);
							}
						}
					}
					try {
                        //关键方法
						processbean(beanname, type);
					}
					catch (throwable ex) {
						throw new beaninitializationexception("failed to process @eventlistener " +
								"annotation on bean with name '" + beanname + "'", ex);
					}
				}
			}
		}
	}

org.springframework.context.event.eventlistenermethodprocessor#processbean,关注下面代码的注释,主要逻辑就是会遍历所有单例池中的对象,找到对象中加@eventlistener注解的方法,然后通过eventlistenerfactory将方法设置成监听器,注册到spring容器中

private void processbean(final string beanname, final class<?> targettype) {
		if (!this.nonannotatedclasses.contains(targettype) &&
				annotationutils.iscandidateclass(targettype, eventlistener.class) &&
				!isspringcontainerclass(targettype)) {

			// 找到所有加了@eventlistener注解的方法
			map<method, eventlistener> annotatedmethods = null;
			try {
				annotatedmethods = methodintrospector.selectmethods(targettype,
						(methodintrospector.metadatalookup<eventlistener>) method ->
								annotatedelementutils.findmergedannotation(method, eventlistener.class));
			}
			catch (throwable ex) {
				// an unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
				if (logger.isdebugenabled()) {
					logger.debug("could not resolve methods for bean with name '" + beanname + "'", ex);
				}
			}

			if (collectionutils.isempty(annotatedmethods)) {
				this.nonannotatedclasses.add(targettype);
				if (logger.istraceenabled()) {
					logger.trace("no @eventlistener annotations found on bean class: " + targettype.getname());
				}
			}
			else {
				// non-empty set of methods
				configurableapplicationcontext context = this.applicationcontext;
				assert.state(context != null, "no applicationcontext set");
				list<eventlistenerfactory> factories = this.eventlistenerfactories;
				assert.state(factories != null, "eventlistenerfactory list not initialized");
				for (method method : annotatedmethods.keyset()) {
					for (eventlistenerfactory factory : factories) {
						// 利用eventlistenerfactory来对加了@eventlistener注解的方法生成applicationlistener对象
						if (factory.supportsmethod(method)) {
							method methodtouse = aoputils.selectinvocablemethod(method, context.gettype(beanname));
							applicationlistener<?> applicationlistener =
									factory.createapplicationlistener(beanname, targettype, methodtouse);
							if (applicationlistener instanceof applicationlistenermethodadapter) {
								((applicationlistenermethodadapter) applicationlistener).init(context, this.evaluator);
							}
							context.addapplicationlistener(applicationlistener);
							break;
						}
					}
				}
				if (logger.isdebugenabled()) {
					logger.debug(annotatedmethods.size() + " @eventlistener methods processed on bean '" +
							beanname + "': " + annotatedmethods);
				}
			}
		}
	}

发布事件,生效

容器初始化后,设置的监听器会收到容器初始化完成的事件,然后执行自定义的监听事件

容器初始化最后阶段,即执行org.springframework.context.support.abstractapplicationcontext#finishrefresh

最终效果图为:

总结

eventlistenermethodprocessor和defaulteventlistenerfactory两个类是注解eventlistener的逻辑处理类,先在spring容器初始化阶段先显示引入这两个类的bean定义,然后spring容器在执行beanfactory的后置处理器逻辑时,对这两个类进行实例化;

最后待所有非懒加载单例bean都初始化完后,执行eventlistenermethodprocessor的aftersingletonsinstantiated即初始化后方法,识别出所有加了注解eventlistener的方法,将这些方法用defaulteventlistenerfactory封装成监听器类,注册到spring容器中。

待发布事件时,再从spring容器中获取所有监听器类,回调监听方法。

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

(0)

相关文章:

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

发表评论

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