Coder 爱翻译 How Tomcat Works 第八章 第二部分
The Loader Interface
在web应用里加载servlet和加载其它类都是有一定的规则的。例如:应用里的一个servlet可以使用部署在WEB-INF/classes目录及其子目录下的类。但是,servlet不能访问其它类,甚至是包含在JVM运行的Tomcat的CLASSPATH下的类。同样一个servlet也只能访问WEB-INF/lib目录下的类库,不能访问其他目录下的类库。
Tomcat的加载器代表了一个web应用的加载器,而不是一个类加载器。一个加载器必须实现org.apache.catalina.Loader接口。这个加载器实现使用一个
org.apache.catalina.loader.WebappClassLoader类表示的特定类的加载器。你可以在一个web加载器中使用Loader接口的getClassLoader方法来获取一个ClassLoader。
Loader接口定义了与一个仓库(repository)集合一起工作的方法。一个应用的WEB-INF/classes和WEB-INF/lib是目录作为仓库而被添加。Loader接口的addRepository方法用来添加一个仓库,findRepositories方法返回包含了所有仓库的一个数组。
一个Tomcat的加载器实现通常和是一个context相关联的,Loader接口的getContainer和setContainer方法用来在它们之间建立联系。如果在一个context里有一个或多个类被改变,加载器也支持重新加载。这样,servlet程序员编译一个servlet或者一个类,这个新的类在不需要重启Tomcat的情况下会被重新加载。为了实现重新加载,Loader接口有modified方法。在一个加载器实现里,modified方法在仓库中一个或多个类改变了,就返回true。但是一个加载器不会重新加载它自己本身。它调用Context接口的reload方法。其它两个方法:setReloadable和getReloadable用来决定是否使用重新加载这个功能。默认情况,Context的标准实现(org.apache.catalina.core.StandardContext),重新加载是关闭的。要打开context的重新加载功能,你需要在server.xml中添加一个Context元素:
一个加载器实现可以被告知是否使用委托,把它委托给一个父类类加载器。这样,Loader接口提供getDelegate和setDelegate方法。
The Reloader Interface
为了支持自动重新加载,一个类加载器实现必须实现org.apache.catalina.loader.Reloader接口。
也不用首先委托给系统类加载器,不允许你加载属于这些包及其子包下的类:
然我们看看这个类怎么缓存和加载类
Caching
为了获取更好的性能,被加载的类会被缓存起来,以便下次在这个类需要时不需要再次加载。它可以从缓存中取出来。缓存可以在本地处理,缓存是被WebappClassLoader实例管理的。此外,java.lang.ClassLoader维护一个之前被加载过的类的Vector,以防止它这些类被垃圾回收。这种情况,缓存是被它的父类管理的。
每个类会被当做一个资源,它(WEB-INF/classes下或JAR文件里的类文件)是通过WebappClassLoader来加载的。一个资源由org.apache.catalina.loader.ResourceEntry类代表。一个ResourceEntry实例持有类的代表、最后的更改日期、清单(Manifest)等等的字节数组。
然后把两个wrapper加入到context中,添加映射以便context可以定位wrapper。
这几行让docBase和仓库的列表当你运行这个应用程序的时候会被打印出来。// make the application wait until we press a key. System.in.read(); ((Lifecycle) context).stop();
Running the Application
总结:web应用加载器或一个简单的加载器,是Catalina中最重要的一个组件。一个加载器负责加载类和持有一个内部类加载器。这个内部类加载器是一个特定的类,它被Tomcat用来执行某种规则来加载类。这个特定的类加载器支持缓存和检查单个或多个类是否发生变化。
注:把repository翻译为仓库
第八章 完