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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM