tomcat触发ServletContext初始化监听事件的源码(原创)

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);
}
原文地址:https://www.cnblogs.com/hvicen/p/6004819.html