Tomcat请求处理(六) -- Servlet实例创建

来源:互联网 发布:新浪微博客户端mac版 编辑:程序博客网 时间:2024/06/05 10:23
首先,来看一下Servlet的载入过程。 

具体是在org.apache.catalina.core.StandardWrapper#allocate()这个方法中,源代码如下: 

Java代码  收藏代码
  1. public Servlet allocate() throws ServletException {  
  2.   
  3.     if (unloading)  
  4.         throw new ServletException(sm.getString("standardWrapper.unloading", getName()));  
  5.       
  6.     // 是否创建了新的实例  
  7.     boolean newInstance = false;  
  8.       
  9.     // 对非singleThreadModel的Servlet的处理  
  10.   
  11.     // 如果不是SingleThreadedModel,每次都返回相同的实例  
  12.     if (!singleThreadModel) {  
  13.   
  14.         // 初始化Servlet实例  
  15.         if (instance == null) {  
  16.             synchronized (this) {  
  17.                 if (instance == null) {  
  18.                     try {  
  19.                         if (log.isDebugEnabled())  
  20.                             log.debug("Allocating non-STM instance");  
  21.                         // 载入新的实例  
  22.                         instance = loadServlet();  
  23.   
  24.                         if (!singleThreadModel) {  
  25.                             newInstance = true;  
  26.                             // 计数器自增  
  27.                             countAllocated++;  
  28.                         }  
  29.                     } catch (ServletException e) {  
  30.                         throw e;  
  31.                     } catch (Throwable e) {  
  32.                         throw new ServletException(sm.getString("standardWrapper.allocate"), e);  
  33.                     }  
  34.                 }  
  35.             }  
  36.         }  
  37.   
  38.         if (!singleThreadModel) {  
  39.             if (log.isTraceEnabled())  
  40.                 log.trace("  Returning non-STM instance");  
  41.   
  42.             if (!newInstance) {// 没有创建新实例的时候的计数器自增  
  43.                 countAllocated++;  
  44.             }  
  45.             // 直接返回Servlet实例  
  46.             return (instance);  
  47.         }  
  48.     }  
  49.   
  50.     // 下边是对singleThreadModel的Servlet的处理  
  51.     synchronized (instancePool) {  
  52.   
  53.         while (countAllocated >= nInstances) {  
  54.             // Allocate a new instance if possible, or else wait  
  55.             if (nInstances < maxInstances) {  
  56.                 try {  
  57.                     // 将Servlet实例入栈  
  58.                     instancePool.push(loadServlet());  
  59.                     // 实例数自增  
  60.                     nInstances++;  
  61.                 } catch (ServletException e) {  
  62.                     throw e;  
  63.                 } catch (Throwable e) {  
  64.                     throw new ServletException(sm.getString("standardWrapper.allocate"), e);  
  65.                 }  
  66.             } else {  
  67.                 try {  
  68.                     instancePool.wait();  
  69.                 } catch (InterruptedException e) {  
  70.                     ;  
  71.                 }  
  72.             }  
  73.         }  
  74.         if (log.isTraceEnabled())  
  75.             log.trace("  Returning allocated STM instance");  
  76.         countAllocated++;  
  77.         return (Servlet) instancePool.pop();  
  78.   
  79.     }  
  80.   
  81. }  


这段代码分两种情况来载入Servlet实例,一种是singleThreadModel的,每个请求都要创建一个实例,这些实例是放到instancePool中的,另外一种是非singleThreadModel的,它对每一个请求线程都使用同一个实例。对于非singleThreadModel的Servlet,当第一次载入之后就不需要再次构建了。 

下边来大概的看一下具体的载入Servelt的过程,就是#loadServlet()这个方法。方法的细节比较多,大致了解下,主要就是ClassLoader的构建,Servlet实例的创建和Servlet初始化方法的调用3个大的部分。源代码如下: 

Java代码  收藏代码
  1. public synchronized Servlet loadServlet() throws ServletException {  
  2.   
  3.     // 非singleThreadModel模式并且instance已经实例化过的情况直接返回  
  4.     if (!singleThreadModel && (instance != null))  
  5.         return instance;  
  6.   
  7.     PrintStream out = System.out;  
  8.     if (swallowOutput) {  
  9.         SystemLogHandler.startCapture();  
  10.     }  
  11.   
  12.     Servlet servlet;  
  13.     try {  
  14.         long t1 = System.currentTimeMillis();  
  15.         // Servlet的完整类名  
  16.         String actualClass = servletClass;  
  17.         if ((actualClass == null) && (jspFile != null)) {// 如果是JSP文件  
  18.             Wrapper jspWrapper = (Wrapper) ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);  
  19.             if (jspWrapper != null) {  
  20.                 actualClass = jspWrapper.getServletClass();  
  21.                 // Merge init parameters  
  22.                 String paramNames[] = jspWrapper.findInitParameters();  
  23.                 for (int i = 0; i < paramNames.length; i++) {  
  24.                     if (parameters.get(paramNames[i]) == null) {  
  25.                         parameters.put(paramNames[i], jspWrapper.findInitParameter(paramNames[i]));  
  26.                     }  
  27.                 }  
  28.             }  
  29.         }  
  30.   
  31.         // Complain if no servlet class has been specified  
  32.         if (actualClass == null) {  
  33.             unavailable(null);  
  34.             throw new ServletException(sm.getString("standardWrapper.notClass", getName()));  
  35.         }  
  36.   
  37.         // 构建ClassLoader  
  38.         Loader loader = getLoader();  
  39.         if (loader == null) {  
  40.             unavailable(null);  
  41.             throw new ServletException(sm.getString("standardWrapper.missingLoader", getName()));  
  42.         }  
  43.   
  44.         ClassLoader classLoader = loader.getClassLoader();  
  45.   
  46.         if (isContainerProvidedServlet(actualClass) && !((Context) getParent()).getPrivileged()) {  
  47.             classLoader = this.getClass().getClassLoader();  
  48.         }  
  49.   
  50.         Class classClass = null;  
  51.         try {  
  52.             if (SecurityUtil.isPackageProtectionEnabled()) {  
  53.                 final ClassLoader fclassLoader = classLoader;  
  54.                 final String factualClass = actualClass;  
  55.                 try {  
  56.                     classClass = (Class) AccessController.doPrivileged(new PrivilegedExceptionAction() {  
  57.                         public Object run() throws Exception {  
  58.                             if (fclassLoader != null) {  
  59.                                 return fclassLoader.loadClass(factualClass);  
  60.                             } else {  
  61.                                 return Class.forName(factualClass);  
  62.                             }  
  63.                         }  
  64.                     });  
  65.                 } catch (PrivilegedActionException pax) {  
  66.                     Exception ex = pax.getException();  
  67.                     if (ex instanceof ClassNotFoundException) {  
  68.                         throw (ClassNotFoundException) ex;  
  69.                     } else {  
  70.                         getServletContext().log("Error loading " + fclassLoader + " " + factualClass, ex);  
  71.                     }  
  72.                 }  
  73.             } else {  
  74.                 if (classLoader != null) {  
  75.                     classClass = classLoader.loadClass(actualClass);  
  76.                 } else {  
  77.                     classClass = Class.forName(actualClass);  
  78.                 }  
  79.             }  
  80.         } catch (ClassNotFoundException e) {  
  81.             unavailable(null);  
  82.             getServletContext().log("Error loading " + classLoader + " " + actualClass, e);  
  83.             throw new ServletException(sm.getString("standardWrapper.missingClass", actualClass), e);  
  84.         }  
  85.   
  86.         if (classClass == null) {  
  87.             unavailable(null);  
  88.             throw new ServletException(sm.getString("standardWrapper.missingClass", actualClass));  
  89.         }  
  90.   
  91.         // 生成Servlet实例  
  92.         try {  
  93.             servlet = (Servlet) classClass.newInstance();  
  94.             if (!((Context) getParent()).getIgnoreAnnotations()) {  
  95.                 if (getParent() instanceof StandardContext) {  
  96.                     ((StandardContext) getParent()).getAnnotationProcessor().processAnnotations(servlet);  
  97.                     ((StandardContext) getParent()).getAnnotationProcessor().postConstruct(servlet);  
  98.                 }  
  99.             }  
  100.         } catch (ClassCastException e) {  
  101.             unavailable(null);  
  102.             throw new ServletException(sm.getString("standardWrapper.notServlet", actualClass), e);  
  103.         } catch (Throwable e) {  
  104.             unavailable(null);  
  105.             if (log.isDebugEnabled()) {  
  106.                 log.debug(sm.getString("standardWrapper.instantiate", actualClass), e);  
  107.             }  
  108.   
  109.             throw new ServletException(sm.getString("standardWrapper.instantiate", actualClass), e);  
  110.         }  
  111.   
  112.         if (!isServletAllowed(servlet)) {  
  113.             throw new SecurityException(sm.getString("standardWrapper.privilegedServlet", actualClass));  
  114.         }  
  115.   
  116.         if ((servlet instanceof ContainerServlet)  
  117.                 && (isContainerProvidedServlet(actualClass) || ((Context) getParent()).getPrivileged())) {  
  118.             ((ContainerServlet) servlet).setWrapper(this);  
  119.         }  
  120.   
  121.         classLoadTime = (int) (System.currentTimeMillis() - t1);  
  122.   
  123.         // 调用Servelt的初始化方法  
  124.         try {  
  125.             instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT, servlet);  
  126.   
  127.             if (Globals.IS_SECURITY_ENABLED) {  
  128.                 Object[] args = new Object[] { ((ServletConfig) facade) };  
  129.                 SecurityUtil.doAsPrivilege("init", servlet, classType, args);  
  130.                 args = null;  
  131.             } else {  
  132.                 servlet.init(facade);  
  133.             }  
  134.   
  135.             // Invoke jspInit on JSP pages  
  136.             if ((loadOnStartup >= 0) && (jspFile != null)) {  
  137.                 // 调用jspInit()  
  138.                 DummyRequest req = new DummyRequest();  
  139.                 req.setServletPath(jspFile);  
  140.                 req.setQueryString("jsp_precompile=true");  
  141.                 DummyResponse res = new DummyResponse();  
  142.   
  143.                 if (Globals.IS_SECURITY_ENABLED) {  
  144.                     Object[] args = new Object[] { req, res };  
  145.                     SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args);  
  146.                     args = null;  
  147.                 } else {  
  148.                     servlet.service(req, res);  
  149.                 }  
  150.             }  
  151.             instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet);  
  152.         } catch (UnavailableException f) {  
  153.             instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f);  
  154.             unavailable(f);  
  155.             throw f;  
  156.         } catch (ServletException f) {  
  157.             instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f);  
  158.             throw f;  
  159.         } catch (Throwable f) {  
  160.             getServletContext().log("StandardWrapper.Throwable", f);  
  161.             instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT, servlet, f);  
  162.             throw new ServletException(sm.getString("standardWrapper.initException", getName()), f);  
  163.         }  
  164.   
  165.         singleThreadModel = servlet instanceof SingleThreadModel;  
  166.         if (singleThreadModel) {  
  167.             if (instancePool == null)  
  168.                 instancePool = new Stack();  
  169.         }  
  170.         fireContainerEvent("load"this);  
  171.   
  172.         loadTime = System.currentTimeMillis() - t1;  
  173.     } finally {  
  174.         if (swallowOutput) {  
  175.             String log = SystemLogHandler.stopCapture();  
  176.             if (log != null && log.length() > 0) {  
  177.                 if (getServletContext() != null) {  
  178.                     getServletContext().log(log);  
  179.                 } else {  
  180.                     out.println(log);  
  181.                 }  
  182.             }  
  183.         }  
  184.     }  
  185.     return servlet;  
  186.   
  187. }  

另外,在载入JSP文件时,Servlet是org.apache.jasper.servlet.JspServlet的实例,载入静态资源时,Servlet用的是org.apache.catalina.servlets.DefaultServlet实例。 

而JSP页面在后边还有编译等操作,后边还要继续详述。
0 0
原创粉丝点击