tomcat 8.0.36

知识点:

  • 动态监听器的好处可以根据环境条件进行选择性添加。
  • 静态监听器有七类。
  1. ServletContextAttributeListener
  2. ServletRequestListener
  3. ServletRequestAttributeListener
  4. HttpSessionIdListener
  5. HttpSessionAttributeListener
  6. HttpSessionListener
  7. ServletContextListener
  • 动态添加的ServletContextListener,其事件源ServletContext缺失插入性等功能。
  • 在触发ServletContext时,不能再动态添加ServletContextListener,但可以动态添加其它类型的监听器。

获取通过web.xml,web-fragment.xml或者注解等方式配置的监听器集,统称他们为静态监听器集。

为什么称为静态监听器集,因为他们是固定必须添加进来的,相对于动态来说,动态是可以根据所需或者不同的条件,例如servlet api的版本等因素,进行选择性添加。

String listeners[] = findApplicationListeners();

接下来就是定义一个结果集,这个结果集是用于接收监听器实例化后的实例。而实例化的过程也是挺丰富多彩的,例如JNDI注入,POST构造方法调用等,这里就不多叙述了。

Object results[] = new Object[listeners.length];
for (int i = 0; i < results.length; i++) {
String listener = listeners[i];
results[i] = getInstanceManager().newInstance(listener);
}

然后把监听器集的实例区分开来,为什么要区分开来?可能是因为事件类型的触发频率要比生命周期的频率高吧,反正能触发就行。

ArrayList<Object> eventListeners = new ArrayList<>();
ArrayList<Object> lifecycleListeners = new ArrayList<>();
for (int i = 0; i < results.length; i++) {
if ((results[i] instanceof ServletContextAttributeListener)
|| (results[i] instanceof ServletRequestAttributeListener)
|| (results[i] instanceof ServletRequestListener)
|| (results[i] instanceof HttpSessionIdListener)
|| (results[i] instanceof HttpSessionAttributeListener)) {
eventListeners.add(results[i]);
}
if ((results[i] instanceof ServletContextListener)
|| (results[i] instanceof HttpSessionListener)) {
lifecycleListeners.add(results[i]);
}
}

这里就是合并了,当然是与动态监听器集合并,两者合并后就是最终的监听器集。

在合并生命周期类型的监听器集时,会把动态的ServletContextListener存入noPluggabilityListeners,而noPluggabilityListeners的意思是无插入性监听器集,其用途就在后面。

for (Object eventListener : getApplicationEventListeners()) {
eventListeners.add(eventListener);
}
setApplicationEventListeners(eventListeners.toArray()); for (Object lifecycleListener : getApplicationLifecycleListeners()) {
lifecycleListeners.add(lifecycleListener);
if (lifecycleListener instanceof ServletContextListener) {
noPluggabilityListeners.add(lifecycleListener);
}
}
setApplicationLifecycleListeners(lifecycleListeners.toArray());

接着,就是关闭一个选项功能,防止程序在触发ServletContextListener事件时,获取ServletContext再次动态添加ServletContextListener。

context.setNewServletContextListenerAllowed(false);

再接着,创建了两个事件,这两个事件所用到的ServletContext不一样,一个是功能齐全的ServletContext,另一个是noPluggabilityServletContext,意思是无插入功能的ServletContext,当然就是比功能齐全的ServletContext缺失大部份功能。

ServletContextEvent event = new ServletContextEvent(getServletContext());
ServletContextEvent tldEvent = new ServletContextEvent(noPluggabilityServletContext);

最后就是遍历所有ServletContextListener,调用监听方法。如果是动态添加的监听器,是禁止一些操作,所以需要传入无插入性的ServletContext。

Object instances[] = getApplicationLifecycleListeners();
for (int i = 0; i < instances.length; i++) {
if (!(instances[i] instanceof ServletContextListener))
continue;
ServletContextListener listener = (ServletContextListener) instances[i];
try {
if (noPluggabilityListeners.contains(listener)) {
listener.contextInitialized(tldEvent);
} else {
listener.contextInitialized(event);
}
} catch (Throwable t) {
}
}

完整源码:

public boolean listenerStart() {
if (log.isDebugEnabled())
log.debug("Configuring application event listeners"); String listeners[] = findApplicationListeners();
Object results[] = new Object[listeners.length];
boolean ok = true;
for (int i = 0; i < results.length; i++) {
if (getLogger().isDebugEnabled())
getLogger().debug(" Configuring event listener class '" + listeners[i] + "'");
try {
String listener = listeners[i];
results[i] = getInstanceManager().newInstance(listener);
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
getLogger().error(sm.getString("standardContext.applicationListener", listeners[i]), t);
ok = false;
}
}
if (!ok) {
getLogger().error(sm.getString("standardContext.applicationSkipped"));
return (false);
} ArrayList<Object> eventListeners = new ArrayList<>();
ArrayList<Object> lifecycleListeners = new ArrayList<>();
for (int i = 0; i < results.length; i++) {
if ((results[i] instanceof ServletContextAttributeListener)
|| (results[i] instanceof ServletRequestAttributeListener)
|| (results[i] instanceof ServletRequestListener)
|| (results[i] instanceof HttpSessionIdListener)
|| (results[i] instanceof HttpSessionAttributeListener)) {
eventListeners.add(results[i]);
}
if ((results[i] instanceof ServletContextListener)
|| (results[i] instanceof HttpSessionListener)) {
lifecycleListeners.add(results[i]);
}
} for (Object eventListener : getApplicationEventListeners()) {
eventListeners.add(eventListener);
}
setApplicationEventListeners(eventListeners.toArray()); for (Object lifecycleListener : getApplicationLifecycleListeners()) {
lifecycleListeners.add(lifecycleListener);
if (lifecycleListener instanceof ServletContextListener) {
noPluggabilityListeners.add(lifecycleListener);
}
}
setApplicationLifecycleListeners(lifecycleListeners.toArray()); if (getLogger().isDebugEnabled())
getLogger().debug("Sending application start events"); getServletContext();
context.setNewServletContextListenerAllowed(false); Object instances[] = getApplicationLifecycleListeners();
if (instances == null || instances.length == 0) {
return ok;
} ServletContextEvent event = new ServletContextEvent(getServletContext());
ServletContextEvent tldEvent = null;
if (noPluggabilityListeners.size() > 0) {
noPluggabilityServletContext = new NoPluggabilityServletContext(getServletContext());
tldEvent = new ServletContextEvent(noPluggabilityServletContext);
}
for (int i = 0; i < instances.length; i++) {
if (!(instances[i] instanceof ServletContextListener))
continue;
ServletContextListener listener = (ServletContextListener) instances[i];
try {
fireContainerEvent("beforeContextInitialized", listener);
if (noPluggabilityListeners.contains(listener)) {
listener.contextInitialized(tldEvent);
} else {
listener.contextInitialized(event);
}
fireContainerEvent("afterContextInitialized", listener);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
fireContainerEvent("afterContextInitialized", listener);
getLogger().error(sm.getString("standardContext.listenerStart", instances[i].getClass().getName()), t);
ok = false;
}
}
return (ok);
}

tomcat触发ServletContext初始化监听事件的源码(原创)的更多相关文章

  1. memcached(二)事件模型源码分析

    memcachedd事件模型 在memcachedd中,作者为了专注于缓存的设计,使用了libevent来开发事件模型.memcachedd的时间模型同nginx的类似,拥有一个主进行(master) ...

  2. jquery的监听事件和触发事件

    监听事件 $(selector).on('Event me',function(e){ //do something }) 触发事件 $(selector).trigger('Event name') ...

  3. Vue自定义事件,$on(eventName) 监听事件,$emit(eventName) 触发事件

    <!--自定义事件 使用 $on(eventName) 监听事件 使用 $emit(eventName) 触发事件--> <div id="app15"> ...

  4. vue 中监听窗口发生变化,触发监听事件, window.onresize && window.addEventListener('resize',fn) ,window.onresize无效的处理方式

    // 开始这样写,不执行 window.onresize = function() { console.log('窗口发生变化') } // 改成window监听事件 window.addEventL ...

  5. javascript事件有哪些?javascript的监听事件

    事件类型: 1.界面事件 onload:描述文档,图片,css已经frame,object加载完毕时触发,window.onload window.onload = function(){ //代表图 ...

  6. spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情

    <spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...

  7. zookeeper 监听事件 PathChildrenCacheListener

    zookeeper 监听事件 PathChildrenCacheListener PathChildrenCacheListener一次父节点注册,监听每次子节点操作,不监听自身和查询. 1.测试类: ...

  8. zookeeper 监听事件 NodeCacheListener

    zookeeper 监听事件 NodeCacheListener NodeCacheListener一次注册,每次监听,但是监听不到操作类型,不知道是增加?删除?还是修改? 1.测试类: packag ...

  9. 关于AngularJs中监听事件及脏循环的理解

    可能很多刚入行或者刚学习的前端对于AngularJs中的一些事件或者概念感觉不理解或者没有思路,今天让我们一起来剖析一下AngularJs中的一些事件. AngularJs中对于的监听事件会用到一个s ...

随机推荐

  1. Java学习笔记七——数组工具类Arrays

    数组工具类Arrays Java提供的Arrays类里包含的一些static修饰的方法可以直接操作数组.若将里面的方法用熟的话,那开发效率会大大提高.下面介绍其中的方法. List<T> ...

  2. [java基础知识]java安装步骤

    jre:  java运行环境.  jre =  java虚拟机 + 核心类库(辅助java虚拟机运行的文件).如果只是运行java程序,只需要安装jre.    jdk: java开发工具集   jd ...

  3. 移动端web开发 问题

    1.APP 返回按钮 <a href='#' onclick='javascript:history.back(-1);'></a> 返回有问题需要使用 href='javas ...

  4. js禁止重复提交方法

    beforeSend: function () { // 禁用按钮防止重复提交 $("#fileForm a[class='btn blue_btn']").removeAttr( ...

  5. Ajax的同步与异步

    原文地址:http://www.cnblogs.com/Joetao/articles/3525007.html <%@ Page Language="C#" AutoEve ...

  6. wpa_supplicant代码走读

    wpa_supplicant_add_iface wpa_supplicant_init_iface wpa_supplicant_set_driver wpa_config_read wpa_sup ...

  7. How and Where Concurrent Asynchronous I/O with ASP.NET Web API 对异步编程分析的非常的好

    How and Where Concurrent Asynchronous I/O with ASP.NET Web API http://www.tugberkugurlu.com/archive/ ...

  8. 如何重载delegate

    在写delegate的时候遇到一个问题,在已有一个不带参数的delegate基础上,试图再增加一个带参数的delegate,结果VS报了“already contains a definition f ...

  9. 在WebApi中基于Owin OAuth使用授权发放Token

    如何基于Microsoft.Owin.Security.OAuth,使用Client Credentials Grant授权方式给客户端发放access token? Client Credentia ...

  10. 作业七:团队项目——Alpha版本冲刺阶段-10

    部分代码: public void run(){ while (true){ //单击棋子第一下开始闪烁 if (chessManClick){ play[Man].setVisible(false) ...