事件机制

事件机制
  

	相关概念:
		事件EventObject
		事件生成器 				事件的产生者,生成事件后,使用事件发布器发布事件。
		事件生成器工厂 			生产多种类型的事件生成器
		事件发布器EventPublisher 	发布事件:将事件发布到广播器中。
		事件广播器 				通知在事件监听器注册表中注册的事件监听器。即将事件dispatch到对应的监听器上。
		事件监听器EventListener 	监听事件,并做相应的处理。
		事件监听器注册表 			管理事件监听器,广播器通过注册表来寻找指定的监听器。

	执行流程:
		1)初始化监听器注册表。
		2)businessService ---> 生成事件 ---> 发布事件 ---> 广播器:从注册表中获取指定类型的监听器,并通知监听器 ---> 各个监听器响应该事件。

	优点:
		消除不同业务间的耦合关系。

jdk的事件机制:

	事件:EventObject
	未定义事件发布器
	事件监听器:EventListener


spring的事件机制:

	事件:ApplicationEvent
		继承了jdk的EventObject

	事件生成器:spring中并没有定义事件生成器,spring直接通过new ApplicationEvent的实现类来生成事件。

	事件发布器:ApplicationEventPublisher
		实现:
			ApplicationContext继承了ApplicationEventPublisher,即ApplicationContext的实现类作为不同的事件发布器。
			将事件发布到广播器中:AbstractApplicationContext调用广播器的multicastEvent()方法将事件发布到广播器中。

	事件广播器:ApplicationEventMulticaster
		实现:
			默认广播器:SimpleApplicationEventMulticaster
			使用multicastEvent()方法来广播事件:
				从注册表中获取监听器:使用getApplicationListeners()方法从注册表中获取事件监听器。
				通知监听器:使用invokeListener()方法来通知指定的监听器,invokeListener()方法内调用了监听器的onApplicationEvent方法。

	事件监听器:ApplicationListener
		继承了jdk的EventListener

	事件监听器注册表:
		实现:
			数据结构:AbstractApplicationContext的applicationListeners属性:
				private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();
			注册监听器:通过AbstractApplicationContext的addApplicationListener()方法将监听器添加到注册表中。
			初始化:容器启动的时候,会初始化注册表。
				eg:在创建容器和初始化容器时会调用FrameworkServlet.configureAndRefreshWebApplicationContext()方法,该方法会调用addApplicationListener()方法来注册监听器。
		注意:
			广播器ApplicationEventMulticaster也维护了一份监听器的注册表。
			在广播器初始化前,spring会向applicationListeners中注册监听器,
			在广播器初始化后,spring会将applicationListeners中注册的监听器都添加到广播器自己维护的注册表中,并且,之后的监听器会直接注册到广播器自己的注册表中。
			广播器在广播事件时,会通知自己维护的注册表中的监听器。

	说明:
		
	    /**
	     * ApplicationContext(更确切的说是AbstractApplicationContext)在spring的事件机制中扮演了多个角色:事件发布器、事件广播器、监听器注册表
	     */
		public abstract class AbstractApplicationContext implements ApplicationContext {

			// ApplicationContext继承了ApplicationEventPublisher,故AbstractApplicationContext即事件发布器

			// 事件广播器 
			/** Helper class used in event publishing */
			private ApplicationEventMulticaster applicationEventMulticaster;

			// 事件监听器注册表
			private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();

			/** ApplicationEvents published early */
			private Set<ApplicationEvent> earlyApplicationEvents;

			/** Parent context */
			private ApplicationContext parent;


			/**
			 * Load or refresh the persistent representation of the configuration,
			 * which might an XML file, properties file, or relational database schema.
			 */
			@Override
			public void refresh() throws BeansException, IllegalStateException {
				synchronized (this.startupShutdownMonitor) {

					// Prepare this context for refreshing.
					// 这里将earlyApplicationEvents初始化为一个空集合
					prepareRefresh();

					// Tell the subclass to refresh the internal bean factory.
					ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

					// Prepare the bean factory for use in this context.
					prepareBeanFactory(beanFactory);

					try {
						// Allows post-processing of the bean factory in context subclasses.
						postProcessBeanFactory(beanFactory);

						// Invoke factory processors registered as beans in the context.
						invokeBeanFactoryPostProcessors(beanFactory);

						// Register bean processors that intercept bean creation.
						registerBeanPostProcessors(beanFactory);

						// Initialize message source for this context.
						initMessageSource();

						// Initialize event multicaster for this context. 初始化广播器
						initApplicationEventMulticaster();

						// Initialize other special beans in specific context subclasses.
						onRefresh();

						// Check for listener beans and register them. 注册监听器
						// 在监听器注册完成后,会使用广播器将earlyApplicationEvents中缓存的事件广播出去,并将earlyApplicationEvents置为null。
						registerListeners();

						// Instantiate all remaining (non-lazy-init) singletons.
						finishBeanFactoryInitialization(beanFactory);

						// Last step: publish corresponding event.
						finishRefresh();

					} catch (BeansException ex) {
						destroyBeans(); // Destroy already created singletons to avoid dangling resources.
						cancelRefresh(ex); // Reset 'active' flag.
						throw ex; // Propagate exception to caller.
					} finally {
						// Reset common introspection caches in Spring's core, since we might not ever need metadata for singleton beans anymore...
						resetCommonCaches();
					}
				}
			}


			@Override
			public void addApplicationListener(ApplicationListener<?> listener) {
				if (this.applicationEventMulticaster != null) {
					this.applicationEventMulticaster.addApplicationListener(listener);
				} else {
					this.applicationListeners.add(listener);
				}
			}


			// 发布事件
			@Override
			public void publishEvent(ApplicationEvent event) {
				publishEvent(event, null);
			}

			protected void publishEvent(Object event, ResolvableType eventType) {

				// 如果事件的类型不是ApplicationEvent,则将事件包装为PayloadApplicationEvent事件。
				ApplicationEvent applicationEvent;
				if (event instanceof ApplicationEvent) {
					applicationEvent = (ApplicationEvent) event;
				} else {
					applicationEvent = new PayloadApplicationEvent<Object>(this, event);
					if (eventType == null) {
						eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
					}
				}

				// Multicast right now if possible - or lazily once the multicaster is initialized
				// 若广播器还没有初始化,则先将事件缓存到earlyApplicationEvents中,
				// 当 广播器初始化完成 且 监听器全部注册完成 后,spring会将earlyApplicationEvents中的事件广播出去,并将earlyApplicationEvents置为null
				if (this.earlyApplicationEvents != null) {
					this.earlyApplicationEvents.add(applicationEvent);
				} else {
					getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
				}

				// Publish event via parent context as well...
				if (this.parent != null) {
					if (this.parent instanceof AbstractApplicationContext) {
						((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
					} else {
						this.parent.publishEvent(event);
					}
				}
			}

		}


	举例:
		duboo服务的导出:
			监听器:ServiceBean
				ServiceBean实现了spring的ApplicationListener接口,并且监听着spring的上下文刷新事件(ContextRefreshedEvent),当监听到spring的上下文刷新事件时,执行服务导出操作。






 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值