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 事件模式 源代码导读的更多相关文章
- Spring 事件监听机制及原理分析
简介 在JAVA体系中,有支持实现事件监听机制,在Spring 中也专门提供了一套事件机制的接口,方便我们实现.比如我们可以实现当用户注册后,给他发送一封邮件告诉他注册成功的一些信息,比如用户订阅的主 ...
- spring发布和接收定制的事件(spring事件传播)
spring发布和接收定制的事件(spring事件传播) 2012-12-26 20:05 22111人阅读 评论(2) 收藏 举报 分类: 开源技术(如Struts/spring/Hibernat ...
- 【转载】详细解读C#中的 .NET 弱事件模式
你可能知道,事件处理是内存泄漏的一个常见来源,它由不再使用的对象存留产生,你也许认为它们应该已经被回收了,但不是,并有充分的理由. 在这个短文中(期望如此),我会在 .Net 框架的上下文事件处理中展 ...
- C#中的 .NET 弱事件模式
引言 你可能知道,事件处理是内存泄漏的一个常见来源,它由不再使用的对象存留产生,你也许认为它们应该已经被回收了,但不是,并有充分的理由. 在这个短文中(期望如此),我会在 .Net 框架的上下文事件处 ...
- spring 事件(Application Event)
spring 事件为bean 与 bean之间传递消息.一个bean处理完了希望其余一个接着处理.这时我们就需要其余的一个bean监听当前bean所发送的事件. spring事件使用步骤如下: 1.先 ...
- C#代码:用事件模式实现通知
事件提供了一种标准的机制来通知监听者..NET的事件模式使用了事件语法来实现观察者模式.任意数量的客户对象都可以将自己的处理函数注册到事件上,然后处理这些事件.这些客户对象不需要再编译期就给出.时间也 ...
- Spring mvc 模式小结
http://www.taobaotesting.com/blogs/2375 1.spring mvc简介 Spring MVC框架是一个MVC框架,通过实现Model-View-Controlle ...
- Qt中事件分发源代码剖析(一共8个步骤,顺序非常清楚:全局的事件过滤器,再传递给目标对象的事件过滤器,最终传递给目标对象)
Qt中事件分发源代码剖析 Qt中事件传递顺序: 在一个应该程序中,会进入一个事件循环,接受系统产生的事件,并且进行分发,这些都是在exec中进行的.下面举例说明: 1)首先看看下面一段示例代码: in ...
- Spring事件解析
首先介绍Spring事件相关类的关系: 其中EventListener与EventObject均是Java SE的范畴,源码如下: package java.util; public interfac ...
随机推荐
- Day16模块
Day16 当做执行文件时 __name__ = "__main__" 当做模块被导入时 __name__ 等于文件名即模块名 ```python 循环导入(模块的名称空间已经建立 ...
- dbfread报错ValueError错误解决方法
问题 我在用dbfread处理.dbf数据的时候出现了报错 ValueError("could not convert string to float: b'.'",) 然后查找. ...
- opencv中相关的矩阵运算
一.矩阵Mat I,img,I1,I2,dst,A,B;double k,alpha;Scalar s;1.加法I=I1+I2;//等同add(I1,I2,I);add(I1,I2,dst,mask, ...
- tomcat 修改默认端口8080 为 80端口
首先,找到你的安装目录,如图: 打开server.xml文件,找到8080,如图: 将 8080 改成你想要的端口,如 80 即可.改完后,记得要重启tomcat! 将端口改成 80 后,访问就不需 ...
- H5系列之地理位置(必知必会)
H5之地理位置必知必会 [02]概念 规范地址:http://www.w3.org/TR/geolocation-API/ HTML5 Geolocation(地理定位)用于定位用 ...
- Centos7 安装配置优化mysql(mariadb分支)
1.说明 由于在centos7的yum仓库中没有mysql,centos7用mariadb替代了mysql. mariadb是mysql源代码的一个分支, mysql被ORACLE闭源,而mariad ...
- Git x SVN rebase事故
Git x SVN rebase事故 @author ixenos 2019-01-09 14:21:21 前言: 昨天在Git x SVN 中进行git svn dcommit的时候,提示需要再进行 ...
- 【java基础 5】树形结构数据加载的思考
前面两篇文章,分别介绍了使用递归和非递归算法加载树形结构数据的方式,本篇文章,则是自己闲下来的时候,进行的一点小思考. 一.什么地方会用到树形结构 刚开始一看到这种结构的时候,最先是想到了家谱.家谱就 ...
- sublime text2-text3 定义的不同浏览器的预览快捷键
sublime text3 自己定义的不同浏览器的预览快捷键突然全部失效了,搞到现在一直没闹清楚怎么回事,翻看插件发现SideBarEnhancements这插件刚更新了,快捷键也是依赖这个插件弄得. ...
- Codeforces983E. NN country
新鲜出炉! $n \leq 200000$的树,给$m \leq 200000$条链,$q \leq 200000$个询问,每次问一条询问链最少用m条中的几条给定链覆盖其所有边,可能无解. 首先确定一 ...