前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring 事件传播机制分析

Spring 事件传播机制分析

作者头像
技术蓝海
发布2018-04-26 14:26:04
8820
发布2018-04-26 14:26:04
举报
文章被收录于专栏:wannshan(javaer,RPC)wannshan(javaer,RPC)

Spring4.0.4

Spring 事件机制采用的是观察者模型(又叫订阅发布模型)

有以下角色

这里,观察者就是监听者,被观察者就是事件对象。

事件发布流程如下

下面以ClassPathXmlApplicationContext初始化完后,发布,容器完成事件,为例说明

代码语言:javascript
复制
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("xxx.xml");

执行以上模板代码,启动Spring容器时,会调用

代码语言:javascript
复制
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
		throws BeansException {

	super(parent);
	setConfigLocations(configLocations);
	if (refresh) {
		refresh();//在父类AbstractApplicationContext中实现
	}
}

AbstractApplicationContext类方法

代码语言:javascript
复制
@Override
public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
		// Prepare this context for refreshing.
		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
			//注册系统里的监听者(观察者)
			registerListeners();

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

			// Last step: publish corresponding event.
			//spring完成了容器启动。就发了一个事件通知监听者
			finishRefresh();
		}

		catch (BeansException ex) {
			// Destroy already created singletons to avoid dangling resources.
			destroyBeans();

			// Reset 'active' flag.
			cancelRefresh(ex);

			// Propagate exception to caller.
			throw ex;
		}
	}
}

以上即使Spring启动流程,也是Spring模板方法模式的体现

// Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Initialize other special beans in specific context subclasses. onRefresh();//都是在子类实现的,,题外话。接着,看finishRefresh()

代码语言:javascript
复制
	protected void finishRefresh() {
		// Initialize lifecycle processor for this context.
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// Publish the final event.//发送一个完成事件ContextRefreshedEvent
		//ContextRefreshedEvent 继承自 ApplicationContextEvent
		//ApplicationContextEvent 继承自 ApplicationEvent 
		//由于AbstractApplicationContext实现了ApplicationEventPublisher接口,所以它本身就是发布者
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		LiveBeansView.registerApplicationContext(this);
	}

再看publishEvent实现

代码语言:javascript
复制
	@Override
	public void publishEvent(ApplicationEvent event) {
		Assert.notNull(event, "Event must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Publishing event in " + getDisplayName() + ": " + event);
		}
		getApplicationEventMulticaster().multicastEvent(event);//获得事件广播器,广播事件。
		if (this.parent != null) {
			this.parent.publishEvent(event);//调用父类发布方法向上传播
		}
	}
	/**
	 * Return the internal ApplicationEventMulticaster used by the context.
	 * @return the internal ApplicationEventMulticaster (never {@code null})
	 * @throws IllegalStateException if the context has not been initialized yet
	 */
	ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
		if (this.applicationEventMulticaster == null) {
			throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
					"call 'refresh' before multicasting events via the context: " + this);
		}
		return this.applicationEventMulticaster;//广播器了已提前初始化好,前面refresh()方法里调用initApplicationEventMulticaster()实现。
	}

//具体
		/**
	 * Initialize the ApplicationEventMulticaster.
	 * Uses SimpleApplicationEventMulticaster if none defined in the context.
	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
	 */
	protected void initApplicationEventMulticaster() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {//可以自定义广播器,名字要取applicationEventMulticaster
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);//记得实现ApplicationEventMulticaster
			if (logger.isDebugEnabled()) {
				logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);//没有就默认这个,Spring 自实现的,是个内部类,下面会看到它的multicastEvent(final ApplicationEvent event)方法
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);//注册,广播器是单例的。
			if (logger.isDebugEnabled()) {
				logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
						APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
						"': using default [" + this.applicationEventMulticaster + "]");
			}
		}
	}
代码语言:javascript
复制
	//看看multicastEvent方法
	public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

        //.....

	@Override
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void multicastEvent(final ApplicationEvent event) {
	//getApplicationListeners(event),获取listeners 调用listener.onApplicationEvent(event);通知
	//getApplicationListeners方法在AbstractApplicationEventMulticaster类实现
		for (final ApplicationListener listener : getApplicationListeners(event)) {
			Executor executor = getTaskExecutor();
			if (executor != null) {//有线程池,还能异步执行。
				executor.execute(new Runnable() {
					@Override
					public void run() {
						listener.onApplicationEvent(event);
					}
				});
			}
			else {
				listener.onApplicationEvent(event);
			}
		}
	}

}

//AbstractApplicationEventMulticaster类中的实现

代码语言:javascript
复制
	 * Return a Collection of ApplicationListeners matching the given
	 * event type. Non-matching listeners get excluded early.
	 * @param event the event to be propagated. Allows for excluding
	 * non-matching listeners early, based on cached matching information.
	 * @return a Collection of ApplicationListeners
	 * @see org.springframework.context.ApplicationListener
	 */
	protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event) {
		Class<? extends ApplicationEvent> eventType = event.getClass();
		Object source = event.getSource();
		Class<?> sourceType = (source != null ? source.getClass() : null);
		ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
		ListenerRetriever retriever = this.retrieverCache.get(cacheKey);//这里用到了cache
		//所有的listener对象,都放在retriever里的,
		if (retriever != null) {//有缓存,就直接返回。
			return retriever.getApplicationListeners();
		}
		else {
			retriever = new ListenerRetriever(true);
			LinkedList<ApplicationListener<?>> allListeners = new LinkedList<ApplicationListener<?>>();
			Set<ApplicationListener<?>> listeners;
			Set<String> listenerBeans;
			synchronized (this.defaultRetriever) {
			//开始疑惑this.defaultRetriever.applicationListeners从哪来,其实这个是
			//AbstractApplicationContext通过addApplicationListener方法手动加进来的,这是个public方法,为配置监听器提供了更大的灵活性
				listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
				listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
			}
			for (ApplicationListener<?> listener : listeners) {
			         //这里要注意下,有个验证监听者和事件类型匹配操作
				 //具体验证法就是 监听器的接收事件类型是不是与当前类型匹配,用的是Class.isAssignableFrom这个方法。
				if (supportsEvent(listener, eventType, sourceType)) {
					retriever.applicationListeners.add(listener);
					allListeners.add(listener);
				}
			}
			if (!listenerBeans.isEmpty()) {
				BeanFactory beanFactory = getBeanFactory();
				for (String listenerBeanName : listenerBeans) {
					try {
						Class<?> listenerType = beanFactory.getType(listenerBeanName);
						//验证
						if (listenerType == null || supportsEvent(listenerType, event)) {
							ApplicationListener<?> listener =
									beanFactory.getBean(listenerBeanName, ApplicationListener.class);
							//验证
							if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
								retriever.applicationListenerBeans.add(listenerBeanName);
								allListeners.add(listener);
							}
						}
					}
					catch (NoSuchBeanDefinitionException ex) {
						// Singleton listener instance (without backing bean definition) disappeared -
						// probably in the middle of the destruction phase
					}
				}
			}
			OrderComparator.sort(allListeners);
			if (this.beanClassLoader == null ||
					(ClassUtils.isCacheSafe(eventType, this.beanClassLoader) &&
							(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
				this.retrieverCache.put(cacheKey, retriever);
			}
			return allListeners;
		}
	}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档