package org.apache.catalina; import java.beans.PropertyChangeListener; public interface Loader { public ClassLoader getClassLoader(); public Container getContainer(); //載入器通常與一個context級別的容器相聯 public void setContainer(Container container); public DefaultContext getDefaultContext(); public void setDefaultContext(DefaultContext defaultContext); public boolean getDelegate(); //Delegate 代表 委托 public void setDelegate(boolean delegate); //就是類加載器是否會把加載的任務委托給其父類加載器 public String getInfo(); public boolean getReloadable(); //表明是否支持載入器的自動重載 public void setReloadable(boolean reloadable); public void addPropertyChangeListener(PropertyChangeListener listener); public void addRepository(String repository); public String[] findRepositories(); public boolean modified(); //如果容器中的一個或多個類被修改了 modified就會返回true public void removePropertyChangeListener(PropertyChangeListenerlistener); }
private WebappClassLoader createClassLoader() throws Exception { //loadClass為字符串 //默認為 private String loaderClass =org.apache.catalina.loader.WebappClassLoader; //可通過setLoadClass方法更改 Class clazz = Class.forName(loaderClass); WebappClassLoader classLoader = null; //在構造WebAppLoader時 又構造函數的參數指定 if (parentClassLoader == null) { // Will cause a ClassCast is the class does not extend WCL, but // this is on purpose (the exception will be caught and rethrown) classLoader = (WebappClassLoader) clazz.newInstance(); } else { Class[] argTypes = { ClassLoader.class }; Object[] args = { parentClassLoader }; Constructor constr = clazz.getConstructor(argTypes); classLoader = (WebappClassLoader) constr.newInstance(args); } return classLoader; }
public void run() { if (debug >= 1) log(BACKGROUND THREAD Starting); // Loop until the termination semaphore is set //整段代碼包含在while循環中 //在前面threadDone已經被設置為false //直到程序關閉時,threadDone才會變為true while (!threadDone) { // Wait for our check interval threadSleep(); if (!started) break; try { // Perform our modification check if (!classLoader.modified()) continue; } catch (Exception e) { log(sm.getString(webappLoader.failModifiedCheck), e); continue; } // Handle a need for reloading notifyContext(); break; } if (debug >= 1) log(BACKGROUND THREAD Stopping); } private void threadSleep() { //讓程序休眠一段時間 時間由checkInterval指定 try { Thread.sleep(checkInterval * 1000L); } catch (InterruptedException e) { ; } }
private void notifyContext() { WebappContextNotifier notifier = new WebappContextNotifier(); (new Thread(notifier)).start(); } protected class WebappContextNotifier implements Runnable { /** * Perform the requested notification. */ public void run() { ((Context) container).reload(); } }WebappContextNotifier是webapploader的內部類。
private static final String[] packageTriggers = { javax, // Java extensions org.xml.sax, // SAX 1 & 2 org.w3c.dom, // DOM 1 & 2 org.apache.xerces, // Xerces 1 & 2 org.apache.xalan // Xalan };
為了達到更好的性能,會緩存已經載入的類,這樣一來下次在使用這個類的時候,就不用再起加載了。
緩存分兩級,一級在本地執行,由webappclassloader實例來管理。package org.apache.catalina.loader; import java.net.URL; import java.security.cert.Certificate; import java.util.jar.Manifest; public class ResourceEntry { public long lastModifled = -1; // Binary content of the resource.public byte[] binaryContent = null; public Class loadedClass = null; // URL source from where the object was loaded. public URL source = null; // URL of the codebase from where the object was loaded. public URL CodeBase = null; public Manifest manifest = null; public Certificate[] certificates = null; }