spring 事件模式 源码导读

一,jdk 事件对象基类
package java.util;

import java.io.Serializable;

public class EventObject
  implements Serializable
{
  protected transient Object source;

  public Object getSource()
  {
    return this.source;
  }

  public EventObject(Object paramObject)
  {
    if (paramObject == null)
      throw new IllegalArgumentException("null source");
    this.source = paramObject;
  }

  public String toString()
  {
    return getClass().getName() + "[source=" + this.source + "]";
  }
}
2,spring事件基类
public abstract class ApplicationEvent extends EventObject {

	/** use serialVersionUID from Spring 1.2 for interoperability */
	private static final long serialVersionUID = 7099057708183571937L;

	/** System time when the event happened */
	private final long timestamp;

	/**
	 * Create a new ApplicationEvent.
	 * @param source the component that published the event (never <code>null</code>)
	 */
	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}

	/**
	 * Return the system time in milliseconds when the event happened.
	 */
	public final long getTimestamp() {
		return this.timestamp;
	}

}
3,ApplicationContextEvent基类
public abstract class ApplicationContextEvent extends ApplicationEvent {

	/**
	 * Create a new ContextStartedEvent.
	 * @param source the <code>ApplicationContext</code> that the event is raised for
	 * (must not be <code>null</code>)
	 */
	public ApplicationContextEvent(ApplicationContext source) {
		super(source);
	}

	/**
	 * Get the <code>ApplicationContext</code> that the event was raised for.
	 */
	public final ApplicationContext getApplicationContext() {
		return (ApplicationContext) getSource();
	}

}
4,容器关闭事件
public class ContextClosedEvent extends ApplicationContextEvent {

	/**
	 * Creates a new ContextClosedEvent.
	 * @param source the <code>ApplicationContext</code> that has been closed
	 * (must not be <code>null</code>)
	 */
	public ContextClosedEvent(ApplicationContext source) {
		super(source);
	}

}
5,AbstractApplicationContext中fireclose事件

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

6,事件处理监听器控制器(SimpleApplicationEventMulticaster)
	@SuppressWarnings("unchecked")
	public void multicastEvent(final ApplicationEvent event) {
		for (final ApplicationListener listener : getApplicationListeners(event)) {
			Executor executor = getTaskExecutor();
			if (executor != null) {
				executor.execute(new Runnable() {
					@SuppressWarnings("unchecked")
					public void run() {
						listener.onApplicationEvent(event);
					}
				});
			}
			else {
				listener.onApplicationEvent(event);
			}
		}
	}
7,AbstractApplicationEventMulticaster获取注册close事件的监听器
	protected Collection<applicationlistener> getApplicationListeners(ApplicationEvent event) {
		Class<? extends ApplicationEvent> eventType = event.getClass();
		Class sourceType = event.getSource().getClass();
		ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
		ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
		if (retriever != null) {
			return retriever.getApplicationListeners();
		}
		else {
			retriever = new ListenerRetriever(true);
			LinkedList<applicationlistener> allListeners = new LinkedList<applicationlistener>();
			synchronized (this.defaultRetriever) {
				for (ApplicationListener listener : this.defaultRetriever.applicationListeners) {
					if (supportsEvent(listener, eventType, sourceType)) {
						retriever.applicationListeners.add(listener);
						allListeners.add(listener);
					}
				}
				if (!this.defaultRetriever.applicationListenerBeans.isEmpty()) {
					BeanFactory beanFactory = getBeanFactory();
					for (String listenerBeanName : this.defaultRetriever.applicationListenerBeans) {
						ApplicationListener listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
						if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
							retriever.applicationListenerBeans.add(listenerBeanName);
							allListeners.add(listener);
						}
					}
				}
				OrderComparator.sort(allListeners);
				this.retrieverCache.put(cacheKey, retriever);
			}
			return allListeners;
		}
	}

二,
1,监听器基类
public  interface EventListener
{
}
2,spring监听器基类
public interface ApplicationListener<e extends="" applicationevent=""> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}
3,AbstractApplicationContext添加监听
	public void addApplicationListener(ApplicationListener<?> listener) {
		if (this.applicationEventMulticaster != null) {
			this.applicationEventMulticaster.addApplicationListener(listener);
		}
		else {
			this.applicationListeners.add(listener);
		}
	}
4,添加listenner到AbstractApplicationEventMulticaster
public void addApplicationListener(ApplicationListener listener) {
		synchronized (this.defaultRetriever) {
			this.defaultRetriever.applicationListeners.add(listener);
			this.retrieverCache.clear();
		}
	}
5,监听处理类注册入口AbstractApplicationContext
		public Object postProcessAfterInitialization(Object bean, String beanName) {
			if (bean instanceof ApplicationListener) {
				// potentially not detected as a listener by getBeanNamesForType retrieval
				Boolean flag = this.singletonNames.get(beanName);
				if (Boolean.TRUE.equals(flag)) {
					// singleton bean (top-level or inner): register on the fly
					addApplicationListener((ApplicationListener<?>) bean);
				}
				else if (flag == null) {
					if (logger.isWarnEnabled() && !containsBean(beanName)) {
						// inner bean with other scope - can't reliably process events
						logger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +
								"but is not reachable for event multicasting by its containing ApplicationContext " +
								"because it does not have singleton scope. Only top-level listener beans are allowed " +
								"to be of non-singleton scope.");
					}
					this.singletonNames.put(beanName, Boolean.FALSE);
				}
			}
			return bean;
		}

</e></applicationlistener></applicationlistener></applicationlistener>

spring 事件模式 源码导读

时间: 2024-08-05 08:48:32

spring 事件模式 源码导读的相关文章

Spring事件监听器源码

Spring 自定义了继承 JDK 事件监听器的接口ApplicationListener<E extends ApplicationEvent> extends EventListener,用来监听 Spring 应用程序中的事件:自定义了继承 JDK 事件对象的抽象类ApplicationEvent extends EventObject,用来表示 Spring 应用程序中的事件类型.容器启动刷新过程中,可以定义事件监听器,来监听应用程序上下文事件ApplicationContextEve

Spring IOC 容器源码分析 - 余下的初始化工作

1. 简介 本篇文章是"Spring IOC 容器源码分析"系列文章的最后一篇文章,本篇文章所分析的对象是 initializeBean 方法,该方法用于对已完成属性填充的 bean 做最后的初始化工作.相较于之前几篇文章所分析的源码,initializeBean 的源码相对比较简单,大家可以愉快的阅读.好了,其他的不多说了,我们直入主题吧. 2. 源码分析 本章我们来分析一下 initializeBean 方法的源码.在完成分析后,还是像往常一样,把方法的执行流程列出来.好了,看源码

Spring IOC 容器源码分析

前言: Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文并不能让你成为 Spring 专家,不过一定有助于大家理解 Spring 的很多概念,帮助大家排查应用中和 Spring 相关的一些问题. 阅读建议:读者至少需要知道怎么配置 Spring,了解 Spring 中的各种概念,少部分内容我还假设读者使用过 SpringMVC.本文要说的 IOC

Spring mvc之源码 handlerMapping和handlerAdapter分析

Spring mvc之源码 handlerMapping和handlerAdapter分析 本篇并不是具体分析Spring mvc,所以好多细节都是一笔带过,主要是带大家梳理一下整个Spring mvc的执行流程,以及如何根据URL查找处理器Controller的实现 (适合那些刚阅读源码不知道如何下手的人) http://www.guojinbao.com/borrow/borrowDetail/GETadLPjnf0[d].do 如何根据URL地址---->找到正确处理器Controller

Spring IOC 容器源码分析 - 创建单例 bean 的过程

1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去创建,而是从缓存中获取.如果某个 bean 还未实例化,这个时候就无法命中缓存.此时,就要根据 bean 的配置信息去创建这个 bean 了.相较于getBean(String)方法的实现逻辑,创建 bean 的方法createBean(String, RootBeanDefinition, Obj

Spring Developer Tools 源码分析:二、类路径监控

在 Spring Developer Tools 源码分析一中介绍了 devtools 提供的文件监控实现,在第二部分中,我们将会使用第一部分提供的目录监控功能,实现对开发环境中 classpath 的监控. 二.类路径监控 首先看一些这一部分可能涉及到的类图: 在图中,红色斜线左上部分是第一部分中介绍的文件目录监控的类,其中 FileSystemWatcher 会通过独立线程监控指定的目录,当目录内容发生变化时,通过对比快照可以获得所有监控目录变化的文件ChangedFiles,然后将变化通知

Spring Security 解析(七) —— Spring Security Oauth2 源码解析

Spring Security 解析(七) -- Spring Security Oauth2 源码解析 ??在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决定先把Spring Security .Spring Security Oauth2 等权限.认证相关的内容.原理及设计学习并整理一遍.本系列文章就是在学习的过程中加强印象和理解所撰写的,如有侵权请告知. 项目环境: JDK1.8 Spring boot 2.x Spring Security

Spring Boot 启动源码解析系列六:执行启动方法一

1234567891011121314151617181920212223242526272829303132333435363738394041424344 public ConfigurableApplicationContext (String... args) { StopWatch stopWatch = new StopWatch(); // 开始执行,记录开始时间 stopWatch.start(); ConfigurableApplicationContext context =

spring framework 4 源码阅读 --- 前期准备

在开始看代码之前,需要做的第一件事是下载代码. 在这里:https://github.com/spring-projects/spring-framework 下载完成了发现使用gradle做的源代码的构建管理工具的. 值得庆幸的事情,spring为导入eclipse写了脚本工具,包解压后结构如下: 发现了一个脚本文件:import-into-eclipse.bat,今天负责导入的就是他了, 等待漫长的编译,这里有个问题,在没有安装gradle的时候,脚本会自动下载gradle 执行完成后是这样