Container容器-tomcat6.x源碼閱讀

2013-09-21java

容器是tomcat的基礎,tomcat經過容器來管理和維護tomcat組件,最外層的容器是Server,最內層的容器是Wrapper,容器提供了一些基礎的功能,例如添加父容器,子容器,共享數據,數據隔離等。web

Container
Container是tomcat中的容器接口,定義了容器所具備的方法和tomcat中容器的規範。容器接口提供了操做容器的方法,例如設置父容器和添加子容器,查找容器,添加監聽容器事件的監聽器,是invoke(Request, Response)處理HTTP協議請求的方法。apache

ContainerBase
ContainerBase是Container接口的基本實現,是個抽象類,在類中提供了Container大多數方法的實現,把一些容器公共實現抽象到ContainerBase實現。ContainerBase的功能是:實現了Container接口的大多數方法,把子類所須要實現的共同方法在基類中實現,避免在子類中重複編碼,子類經過繼承ContainerBase類來完成。數組

LifecycleSupport
ContainerBase抽象類中的屬性,Lifecycle接口實現類,功能是負責管理註冊在容器上面的LifecycleEvent監聽類,監聽容器的生命週期變動,集中管理監聽器。tomcat

listeners
ContainerBase的屬性,容器監聽器數組,用戶監聽容器自己事件,監聽的是ContainerEvent事件,與LifecycleEvent不一樣。安全

Loader
ContainerBase的屬性,tomcat本身封裝的類加載器,針對webapp安全的類加載,管理webapp的類加載,在java的類加載器體系中,不一樣類加載器加載的類實例是不能同時訪問的。session

Manager
ContainerBase的屬性,Manager是用來管理在容器上面的Session池,負責Session的生命週期,從生成到銷燬,Manager是一個管理Session池的一個方法集合接口。app

cluster : Cluster
ContainerBase的屬性,跟集羣有關。webapp

pipeline : Pipeline
ContainerBase的屬性,很重要,是Valve鏈,功能是負責管理Valve,也是請求信息傳遞鏈,最終目的是ServletWrapper中。pipeline 決定Valve的順序,控制請求信息,是容器間傳遞請求信息的橋樑。this

support : PropertyChangeSupport
ContainerBase的屬性,容器屬性更新監聽器集中管理,跟LifecycleSupport功能同樣。

backgroundProcess()
Container接口方法,Container定義該方法的目的是啓用一個後臺進程來處理一些邏輯,好比從新加載配置,判斷Session失效等。

ContainerBackgroundProcessor
ContainerBase基本容器的內部類,實現了Runnable接口,具體做用是做爲一個後臺程序定時觸發backgroundProcess()後臺處理方法。

/**
	 * Private thread class to invoke the backgroundProcess method of this
	 * container and its children after a fixed delay.
	 */
	protected class ContainerBackgroundProcessor implements Runnable {

		public void run() {
			while (!threadDone) {
				try {
					Thread.sleep(backgroundProcessorDelay * 1000L);//睡眠
				} catch (InterruptedException e) {
					;
				}
				if (!threadDone) {
					//取類加載器,確保容器和子容器在同一個類加載器中
					Container parent = (Container) getMappingObject();
					ClassLoader cl = Thread.currentThread()
							.getContextClassLoader();
					if (parent.getLoader() != null) {
						cl = parent.getLoader().getClassLoader();
					}
					processChildren(parent, cl);//調用容器的backgroundProcess()方法
				}
			}
		}

		/**
		 *  處理子容器
		 * @param container
		 * @param cl
		 */
		protected void processChildren(Container container, ClassLoader cl) {
			try {
				if (container.getLoader() != null) {
					Thread.currentThread().setContextClassLoader(
							container.getLoader().getClassLoader());
				}
				container.backgroundProcess();//調用後臺處理方法
			} catch (Throwable t) {
				log.error("Exception invoking periodic operation: ", t);
			} finally {
				Thread.currentThread().setContextClassLoader(cl);
			}
			Container[] children = container.findChildren();
			for (int i = 0; i < children.length; i++) {
				if (children[i].getBackgroundProcessorDelay() <= 0) {
					processChildren(children[i], cl);//處理子容器
				}
			}
		}

	}

init()
負責容器的初始化工做,主要有一下幾步,

  • 註冊到MBeanServer
  • 標記已經初始化
/**
	 * Init method, part of the MBean lifecycle. If the container was added via
	 * JMX, it'll register itself with the parent, using the ObjectName
	 * conventions to locate the parent.
	 * 
	 * If the container was added directly and it doesn't have an ObjectName,
	 * it'll create a name and register itself with the JMX console. On
	 * destroy(), the object will unregister.
	 * 
	 * @throws Exception
	 */
	public void init() throws Exception {

		if (this.getParent() == null) {
			// "Life" update
			ObjectName parentName = getParentName();

			// log.info("Register " + parentName );
			if (parentName != null && mserver.isRegistered(parentName)) {
				mserver.invoke(parentName, "addChild", new Object[] { this },
						new String[] { "org.apache.catalina.Container" });
			}
		}
		initialized = true;
	}

start()
負責容器的啓動工做,主要有如下幾步,主要啓動添加在容器上面的組件。

  • 判斷是否已經啓動
  • 觸發BEFORE_START_EVENT事件,標記已經啓動
  • 啓動類加載器loader,日誌記錄器logger,session管理器manager,集羣節點cluster,權限管理器realm,目錄資源服務resources
  • 啓動子容器
  • 啓動Valve鏈pipeline
  • 觸發START_EVENT事件
  • 啓動後臺任務處理進程
  • 觸發AFTER_START_EVENT事件
/**
	 * Prepare for active use of the public methods of this Component.
	 * 預啓動的公有方法
	 * @exception LifecycleException
	 *                if this component detects a fatal error that prevents it
	 *                from being started
	 */
	public synchronized void start() throws LifecycleException {

		// Validate and update our current component state
		if (started) {
			if (log.isInfoEnabled())
				log.info(sm
						.getString("containerBase.alreadyStarted", logName()));
			return;
		}

		// Notify our interested LifecycleListeners
		//開始啓動事件監聽
		lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);

		started = true;

		// Start our subordinate components, if any
		if ((loader != null) && (loader instanceof Lifecycle))
			((Lifecycle) loader).start();//加載器啓動
		logger = null;
		getLogger();
		if ((logger != null) && (logger instanceof Lifecycle))
			((Lifecycle) logger).start();
		if ((manager != null) && (manager instanceof Lifecycle))
			((Lifecycle) manager).start();//管理器啓動
		if ((cluster != null) && (cluster instanceof Lifecycle))
			((Lifecycle) cluster).start();//集羣從節點啓動
		if ((realm != null) && (realm instanceof Lifecycle))
			((Lifecycle) realm).start();
		if ((resources != null) && (resources instanceof Lifecycle))
			((Lifecycle) resources).start();//資源啓動

		// Start our child containers, if any
		Container children[] = findChildren();
		for (int i = 0; i < children.length; i++) {
			if (children[i] instanceof Lifecycle)
				((Lifecycle) children[i]).start();//啓動子容器
		}

		// Start the Valves in our pipeline (including the basic), if any
		if (pipeline instanceof Lifecycle)
			((Lifecycle) pipeline).start();//監聽pipe功能

		// Notify our interested LifecycleListeners
		//正在啓動事件通知
		lifecycle.fireLifecycleEvent(START_EVENT, null);

		// Start our thread
		threadStart();//啓動線程

		// Notify our interested LifecycleListeners
		//完成啓動事件通知
		lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

	}

stop()
負責中止容器,所作的工做就是按照start()方法中組件啓動的順序逆序中止組件。

/**
	 * Gracefully shut down active use of the public methods of this Component.
	 * 優雅關閉容器的公有方法
	 * @exception LifecycleException
	 *                if this component detects a fatal error that needs to be
	 *                reported
	 */
	public synchronized void stop() throws LifecycleException {

		// Validate and update our current component state
		if (!started) {
			if (log.isInfoEnabled())
				log.info(sm.getString("containerBase.notStarted", logName()));
			return;
		}

		// Notify our interested LifecycleListeners
		//準備中止容器事件通知
		lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);

		// Stop our thread
		threadStop();//中止線程

		// Notify our interested LifecycleListeners
		//中止容器事件通知
		lifecycle.fireLifecycleEvent(STOP_EVENT, null);
		started = false;

		// Stop the Valves in our pipeline (including the basic), if any
		if (pipeline instanceof Lifecycle) {
			((Lifecycle) pipeline).stop();//pipe中止
		}

		// Stop our child containers, if any
		Container children[] = findChildren();
		for (int i = 0; i < children.length; i++) {
			if (children[i] instanceof Lifecycle)
				((Lifecycle) children[i]).stop();//子容器中止
		}
		// Remove children - so next start can work
		children = findChildren();
		for (int i = 0; i < children.length; i++) {
			removeChild(children[i]);//移除子容器
		}

		// Stop our subordinate components, if any
		if ((resources != null) && (resources instanceof Lifecycle)) {
			((Lifecycle) resources).stop();//資源中止
		}
		if ((realm != null) && (realm instanceof Lifecycle)) {
			((Lifecycle) realm).stop();
		}
		if ((cluster != null) && (cluster instanceof Lifecycle)) {
			((Lifecycle) cluster).stop();//集羣子節點中止
		}
		if ((manager != null) && (manager instanceof Lifecycle)) {
			((Lifecycle) manager).stop();//管理器中止
		}
		if ((logger != null) && (logger instanceof Lifecycle)) {
			((Lifecycle) logger).stop();
		}
		if ((loader != null) && (loader instanceof Lifecycle)) {
			((Lifecycle) loader).stop();
		}

		// Notify our interested LifecycleListeners
		//完成中止容器事件通知
		lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);

	}

destroy()
負責銷燬容器,主要工做是註銷MBeanServer,移除父容器引用,移除容器

/**
	 * 中止容器
	 * @throws Exception
	 */
	public void destroy() throws Exception {
		if (started) {
			stop();
		}
		initialized = false;

		// unregister this component
		if (oname != null) {
			try {
				if (controller == oname) {
					Registry.getRegistry(null, null).unregisterComponent(oname);
					if (log.isDebugEnabled())
						log.debug("unregistering " + oname);
				}
			} catch (Throwable t) {
				log.error("Error unregistering ", t);
			}
		}

		if (parent != null) {
			parent.removeChild(this);
		}

		// Stop our child containers, if any
		Container children[] = findChildren();
		for (int i = 0; i < children.length; i++) {
			removeChild(children[i]);
		}

	}

threadStart()
負責啓動容器的後臺任務程序。

/**
	 * Start the background thread that will periodically check for session
	 * timeouts.
	 * 啓動後臺線程並按期檢查session失效
	 */
	protected void threadStart() {

		if (thread != null)
			return;
		if (backgroundProcessorDelay <= 0)
			return;

		threadDone = false;
		String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
		thread = new Thread(new ContainerBackgroundProcessor(), threadName);
		thread.setDaemon(true);//後臺程序
		thread.start();

	}

threadStop()
負責中止後臺進程運行。

/**
	 * Stop the background thread that is periodically checking for session
	 * timeouts.
	 * 中止線程
	 */
	protected void threadStop() {

		if (thread == null)
			return;

		threadDone = true;
		thread.interrupt();//打斷方式中止
		try {
			thread.join();
		} catch (InterruptedException e) {
			;
		}

		thread = null;

	}

從上面的組件和方法能夠看出,容器所需完成的功能或者說是所具有的功能有:

  • 設置父容器,添加管理子容器
  • 管理Session
  • 權限管理
  • 後臺任務處理
  • 生命週期事件監聽
  • 屬性變動事件監聽
  • Valve鏈,過濾請求和響應信息

說好的堅持,老是斷斷續續

相關文章
相關標籤/搜索