我们知道,Servlet 容器最重要的任务就是创建 Servlet 的实例并且调用 Servlet,在前面两期我谈到了 Tomcat 如何定义自己的类加载器来加载 Servlet,但加载 Servlet 的类不等于创建 Servlet 的实例,类加载只是第一步,类加载好了才能创建类的实例,也就是说 Tomcat 先加载 Servlet 的类,然后在 Java 堆上创建了一个 Servlet 实例。
一个 Web 应用里往往有多个 Servlet,而在 Tomcat 中一个 Web 应用对应一个 Context 容器,也就是说一个 Context 容器需要管理多个 Servlet 实例。但 Context 容器并不直接持有 Servlet 实例,而是通过子容器 Wrapper 来管理 Servlet,你可以把 Wrapper 容器看作是 Servlet 的包装。
那为什么需要 Wrapper 呢?Context 容器直接维护一个 Servlet 数组不就行了吗?这是因为 Servlet 不仅仅是一个类实例,它还有相关的配置信息,比如它的 URL 映射、它的初始化参数,因此设计出了一个包装器,把 Servlet 本身和它相关的数据包起来,没错,这就是面向对象的思想。
那管理好 Servlet 就完事大吉了吗?别忘了 Servlet 还有两个兄弟:Listener 和 Filter,它们也是 Servlet 规范中的重要成员,因此 Tomcat 也需要创建它们的实例,也需要在合适的时机去调用它们的方法。