Spring源码分析衍生篇六:Spring监听事件

一、前言

本文是 Spring源码分析:Spring源码分析六:Spring 的刷新 - refresh() 的衍生文章。主要是因为本人菜鸡,在分析源码的过程中还有一些其他的内容不理解,故开设衍生篇来完善内容以学习。

二、简单使用

  1. 自定义监听事件
public class DemoEvent  extends ApplicationEvent {
    
    
    private String msg;
    public DemoEvent(Object source) {
    
    
        super(source);
    }

    public DemoEvent(Object source, String msg) {
    
    
        super(source);
        this.msg = msg;
    }

    public void printMsg(){
    
    
        System.out.println("msg = " + msg);
    }
}
  1. 自定义监听器
@Component
public class DemoListener implements ApplicationListener<DemoEvent> {
    
    
    @Override
    public void onApplicationEvent(DemoEvent event) {
    
    
        event.printMsg();
    }
}
  1. 测试
@SpringBootApplication
public class SpringbootDemoApplication implements ApplicationRunner {
    
    

    public static void main(String[] args) {
    
    
        ConfigurableApplicationContext run = SpringApplication.run(SpringbootDemoApplication.class, args);
        DemoEvent demoEvent = new DemoEvent("", "world");
        run.publishEvent(demoEvent);
    }
}

运行后看到如下:
在这里插入图片描述


当程序运行时,Spring 将会发出 DemoEvent 事件转给DemoListener 监听器,进行进一步的处理。

实际上,Spring是将所有的事件都发送给所有的监听者,这一点在后面的源码分析中可以看出来。

三、源码分析

整个监听事件的流程其实很简单

1. 初始化 事件广播器 - initApplicationEventMulticaster();

initApplicationEventMulticaster 的方法比较简单,考虑了两种情况

  1. 如果用户自定义了事件广播器,在使用用户自定义的事件广播器
  2. 如果用户没有自定义事件广播器,则使用默认的 ApplicationEventMulticaster
	protected void initApplicationEventMulticaster() {
    
    
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		// 如果用户自定义了事件广播器,则使用用户自定义
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
    
    
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isTraceEnabled()) {
    
    
				logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
    
    
			// 否则使用默认的事件广播器 SimpleApplicationEventMulticaster
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			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() + "]");
			}
		}
	}

上面的代码看起来很简单,一般情况下我们都是使用默认的事件广播器SimpleApplicationEventMulticaster

2. 注册监听器 - registerListeners();

	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 listenerBeanName : listenerBeanNames) {
    
    
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}

		// Publish early application events now that we finally have a multicaster...
		// 发布一个早期的Application 事件
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (earlyEventsToProcess != null) {
    
    
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
    
    
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

3. 事件的发布 - publishEvent

我们在 上面的Demo 中, 通过 run.publishEvent(demoEvent); 发布的事件最终会执行如下方法:

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
    
    
		Assert.notNull(event, "Event must not be null");

		// Decorate event as an ApplicationEvent if necessary
		// 分析事件类型
		ApplicationEvent applicationEvent;
		if (event instanceof ApplicationEvent) {
    
    
			applicationEvent = (ApplicationEvent) event;
		}
		else {
    
    
			applicationEvent = new PayloadApplicationEvent<>(this, event);
			if (eventType == null) {
    
    
				eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
			}
		}

		// Multicast right now if possible - or lazily once the multicaster is initialized
		if (this.earlyApplicationEvents != null) {
    
    
			this.earlyApplicationEvents.add(applicationEvent);
		}
		else {
    
    
			// 获取事件广播器进行广播事件广播。我们上面说了一般我们使用默认的事件广播器即 SimpleApplicationEventMulticaster 
			getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
		}

		// Publish event via parent context as well...
		// 寻找父类BeanFactory,继续发布消息
		if (this.parent != null) {
    
    
			if (this.parent instanceof AbstractApplicationContext) {
    
    
				((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
			}
			else {
    
    
				this.parent.publishEvent(event);
			}
		}
	}

我们继续看 multicastEvent 方法如下,可以看到,当Spring事件产生的时候,默认会使用SimpleApplicationEventMulticaster#multicastEvent 方法来广播事件,遍历所有的监听器,并使用监听器中的 onApplicationEvent 方法来进行监听事件的处理。而对于每个监听器来说,其实都可以获取到产生的事件,但使用进行处理由监听器自己决定。

	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
    
    
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		// 获取匹配事件类型的事件事件监听器。比如上面Demo中DemoListener 监听的是DemoEvent 事件类型,这里就是筛选出接受 DemoEvent 类型的监听器。
		
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
    
    
			if (executor != null) {
    
    
				//  在invokeListener 方法中激活调用事件监听器的onApplicationEvent方法
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
    
    
				invokeListener(listener, event);
			}
		}
	}

以上:内容部分参考
《Spring源码深度解析》
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正

猜你喜欢

转载自blog.csdn.net/qq_36882793/article/details/106532790
今日推荐