Spring Event 源码 (四) (事件以及监听器的源码解析)

本文深入探讨了Spring的事件机制,包括配置事件监听器、服务代码中的事件处理以及事件发布。通过分析源码,揭示了事件监听器的创建过程,如后置处理器`EventListenerMethodProcessor`的角色,以及如何通过`@EventListener`注解创建适配器。此外,还阐述了事件发布时的调用流程,涉及观察者模式的应用。总结了事件机制的本质是一个由后置处理器参与的观察者模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.实例代码

在这里插入图片描述

@Configuration
@ComponentScan("com.atguigu.event")
public class EventConfig {
}

监听器

@Component
public class MyApplicationListener implements ApplicationListener<ApplicationEvent> {
    // 监听器如何感知到事件的:
    // ApplicationEvent 和 Payload
    // getApplicationEventMulticaster: 获得多播器, 发送事件
    // 观察者模式: 将所有的事件监听器拿到, 矮个遍历, 调用onApplicationEvent()方法

    // 事件派发: 遍历监听器, 调用onApplicationEvent()方法
    // 发布事件触发
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println(event);
    }
}

服务代码

@Component
public class UserService {
    // EventListenerMethodProcessor, DefaultEventListenerFactory
    // 后置处理和初始化
    // SmartInitializingSingleton: 工厂后置处理环节, 执行增强和所有Bean完全创建好后执行初始化
    // 后置增强环节: EventListenerMethodProcessor.postProcessBeanFactory(): 拿到所有的EventListenerFactory, 排序
    // 初始化环节: afterSingletonsInstantiated():拿到容器中所有的组件, 处理这个组件
    // 1.找到@EventListener 方法
    // 2.遍历每一个方法: 拿到DefaultEventListenerFactory, 当前方法, beanName 封装到适配器中ApplicationListenerMethodAdapter
    // 工厂的作用为创造适配器: 适配器是一个监听器, 多播器注册监听器, 容器注册监听器, 事件派发给的是适配器, 适配器反射调用组件的事件监听方法
    // 标了@EventListener 注解, 就创建适配器, 适配器反射调用方法
    // EventListenerMethodProcessor这个后置处理器为每一个监听方法创建一个监听器组件(适配器)

    // 发布器和监听器
    // 感知的对象
    @EventListener(classes = ApplicationEvent.class)
    public void listener(ApplicationEvent event){
        System.out.println("UserService : " + event);

    }
}

主类

public class MainApplication {
    public static void main(String[] args) {
        /**
         * 事件的发布和监听机制的原理:
         * 获取到EventMulticaster: 事件派发器
         * 事件派发器: getApplicationEventMulticaster(): refresh(): initApplicationEventMulticaster()
         * 容器中有哪些监听器: refresh(): registerListener()
         *
         * @EventListener:
         * EventListenerMethodProcessor->SmartInitializingSingleton, 单实例Bean创建完成后执行
         */
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(EventConfig.class);
        // 发布事件
        context.publishEvent(new ApplicationEvent("1") {
        });
        context.close();
        // ContextRefreshedEvent,source,ContextClosedEvent
    }
}

发布事件

在这里插入图片描述

2.源码分析

  • 创建过程
  • 运行过程
2.1 添加后置处理器源码解析

添加后置处理器为创建过程

在ioc容器启动(this()方法)的时候, 会加载EventListenerMethodProcessor 这个工厂后置处理器

在这里插入图片描述

这个后置处理器实现了SmartInitializingSingletonBeanFactoryPostProcessor 两个接口

SmartInitializingSingleton: 工厂后置处理环节, 执行增强和所有Bean完全创建好后执行初始化

  • 后置增强环节: EventListenerMethodProcessor.postProcessBeanFactory(): 拿到所有的EventListenerFactory, 并排序
  • 初始化环节: afterSingletonsInstantiated():拿到容器中所有的组件, 处理这个组件

在这里插入图片描述

postProcessBeanFactory: 拿到所有的EventListenerFactory, 并进行排序

在这里插入图片描述

afterSingletonsInstantiated: 拿到容器中所有的组件, 处理这个组件

在这里插入图片描述
processBean()

	private void processBean(final String beanName, final Class<?> targetType) {
		if (!this.nonAnnotatedClasses.contains(targetType) &&
				AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
				!isSpringContainerClass(targetType)) {

			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) {
						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);
				}
			}
		}
	}

拿到DefaultEventListenerFactory, 然后封装进适配器中

在这里插入图片描述

  1. 找到@EventListener 方法
  2. 遍历每一个方法: 拿到DefaultEventListenerFactory, 当前方法, beanName 封装到适配器中ApplicationListenerMethodAdapter
  3. 工厂的作用为创造适配器: 适配器是一个监听器, 多播器注册监听器, 容器注册监听器, 事件派发给的是适配器, 适配器反射调用组件的事件监听方法。
    标了@EventListener 注解, 就创建适配器, 适配器反射调用方法。

EventListenerMethodProcessor这个后置处理器为每一个监听方法创建一个监听器组件(适配器)

2.2 发送事件源码分析

发送事件过程为运行事件过程

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

观察者模式: for 循环

在这里插入图片描述

在这里插入图片描述

调用每一个监听器的onApplicationEvent方法

3.总结

事件机制: 1.创建后置处理器, 后置处理器可以创建适配器(监听器) 2.在发布事件的时候, 触发监听器的方法

事件机制简而言之就是观察者模式。不过之前有后置处理器的干预, 然后构建了一个后置处理器参与的观察者模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值