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 ...
随机推荐
- mysql 与QT的连接
第一步:安装 qt开发环境 bi@bi-desktop:~$sudo apt-get install qt4-dev-tools qt4-doc qt4-qtconfig qt4-demos qt4- ...
- DDoS 攻击与防御:从原理到实践(上)
欢迎访问网易云社区,了解更多网易技术产品运营经验. 可怕的 DDoS 出于打击报复.敲诈勒索.政治需要等各种原因,加上攻击成本越来越低.效果特别明显等趋势,DDoS 攻击已经演变成全球性的网络安全威胁 ...
- python基础-对象
1. 对象:一组数据和操作数据方法的集合 >>> class Person(object): ... def __init__(self,name): ... ...
- Charles-安装和配置
一. 安装.破解charles工具 1. 安装压缩包中的charles_setup.exe,安装完成后先不启动charles. 2. 在安装文件中找到crack文件,将文件中的charles.jar拷 ...
- 使用pipework将Docker容器桥接到本地网络环境中
在使用Docker的过程中,有时候我们会有将Docker容器配置到和主机同一网段的需求.要实现这个需求,我们只要将Docker容器和主机的网卡桥接起来,再给Docker容器配上IP就可以了.pipew ...
- centos 7 smplayer vlc播放器
centos7安装多媒体播放器SMPlayer 2017-03-13 21:37:14 分类: LINUX 转自:https://wiki.centos.org/TipsAndTricks/Multi ...
- 汇编CMOS
汇编 端口 端口 前面讲过,各种存储器都和CPU的地址线.数据线.控制线相连.CPU在操控它们的时候,把它们都当作内存来对待,把它们总的看做一个由若干存储单元组成的逻辑存储器,这个逻辑器我们称其为内存 ...
- BZOJ 2179 FFT快速傅立叶 ——FFT
[题目分析] 快速傅里叶变换用于高精度乘法. 其实本质就是循环卷积的计算,也就是多项式的乘法. 两次蝴蝶变换. 二进制取反化递归为迭代. 单位根的巧妙取值,是的复杂度成为了nlogn 范德蒙矩阵计算逆 ...
- Selenium之Web页面滚动条滚操作
//移动到元素element对象的“顶端”与当前窗口的“顶部”对齐 ((JavascriptExecutor) driver).executeScript("arguments[0].scr ...
- C++函数传递指向指针的指针的应用
传递指向指针的引用假设我们想编写一个与前面交换两个整数的 swap 类似的函数,实现两个指针的交换.已知需用 * 定义指针,用 & 定义引用.现在,问题在于如何将这两个操作符结合起来以获得指向 ...