2019-10-28 17:45  阅读(2092)
文章分类:Tomcat 源码分析 文章标签:TomcatTomcat 源码
©  原文作者:clawhub 原文地址:http://clawhub.club

本篇内容源码在StandardWrapperValve的invoke方法中:

        //略......
        //分配一个servlet实例来处理这个请求
        servlet = wrapper.allocate();
        //略......
    

调用StandardWrapper中的方法:

        /**
             * Allocate an initialized instance of this Servlet that is ready to have
             * its <code>service()</code> method called.  If the servlet class does
             * not implement <code>SingleThreadModel</code>, the (only) initialized
             * instance may be returned immediately.  If the servlet class implements
             * <code>SingleThreadModel</code>, the Wrapper implementation must ensure
             * that this instance is not allocated again until it is deallocated by a
             * call to <code>deallocate()</code>.
             * 分配此Servlet的初始化实例,该实例已准备好调用其service()方法。
             * 如果servlet类没有实现SingleThreadModel,则可能立即返回(only)初始化的实例。
             * 如果servlet类实现了SingleThreadModel,
             * 包装器实现必须确保在调用deallocate()释放该实例之前不会再次分配该实例。
             *
             * @exception ServletException if the servlet init() method threw
             *  an exception
             * @exception ServletException if a loading error occurs
             */
            @Override
            public Servlet allocate() throws ServletException {
                //如果当前正在卸载此servlet,则抛出异常
                if (unloading) {
                    throw new ServletException(sm.getString("standardWrapper.unloading", getName()));
                }
                boolean newInstance = false;
    
                // If not SingleThreadedModel, return the same instance every time
                // 如果不是SingleThreadedModel,则每次返回相同的实例
                // singleThreadModel:这个servlet是否实现了SingleThreadModel接口?,这个接口已经被弃用了。
                // 也就是说实现了singleThreadModel接口,每次返回不同的Servlet
                if (!singleThreadModel) {
                    // 如果需要,加载并初始化我们的实例
                    if (instance == null || !instanceInitialized) {
                        synchronized (this) {
                            //如果没有实例的话,加载Servlet
                            if (instance == null) {
                                try {
                                    if (log.isDebugEnabled()) {
                                        log.debug("Allocating non-STM instance");
                                    }
    
                                    // Note: We don't know if the Servlet implements
                                    // SingleThreadModel until we have loaded it.
                                    instance = loadServlet();
                                    newInstance = true;
                                    if (!singleThreadModel) {
                                        // For non-STM, increment here to prevent a race
                                        // condition with unload. Bug 43683, test case
                                        // #3
                                        countAllocated.incrementAndGet();
                                    }
                                } catch (ServletException e) {
                                    throw e;
                                } catch (Throwable e) {
                                    ExceptionUtils.handleThrowable(e);
                                    throw new ServletException(sm.getString("standardWrapper.allocate"), e);
                                }
                            }
                            //如果没有初始化的话,初始化Servlet
                            if (!instanceInitialized) {
                                initServlet(instance);
                            }
                        }
                    }
    
                    if (singleThreadModel) {
                        if (newInstance) {
                            // Have to do this outside of the sync above to prevent a
                            // possible deadlock
                            synchronized (instancePool) {
                                instancePool.push(instance);
                                nInstances++;
                            }
                        }
                    } else {
                        if (log.isTraceEnabled()) {
                            log.trace("  Returning non-STM instance");
                        }
                        // For new instances, count will have been incremented at the
                        // time of creation
                        if (!newInstance) {
                            countAllocated.incrementAndGet();
                        }
                        return instance;
                    }
                }
    
                synchronized (instancePool) {
                    while (countAllocated.get() >= nInstances) {
                        // Allocate a new instance if possible, or else wait
                        if (nInstances < maxInstances) {
                            try {
                                instancePool.push(loadServlet());
                                nInstances++;
                            } catch (ServletException e) {
                                throw e;
                            } catch (Throwable e) {
                                ExceptionUtils.handleThrowable(e);
                                throw new ServletException(sm.getString("standardWrapper.allocate"), e);
                            }
                        } else {
                            try {
                                instancePool.wait();
                            } catch (InterruptedException e) {
                                // Ignore
                            }
                        }
                    }
                    if (log.isTraceEnabled()) {
                        log.trace("  Returning allocated STM instance");
                    }
                    countAllocated.incrementAndGet();
                    return instancePool.pop();
                }
            }
    

其中的loadServlet与initServlet上一篇文章分析过,这里就不看了。此方法最终返回一个Servlet实例。

鉴于这篇文章没啥东西,就一块把deallocate方法看一看:

         /**
             * Return this previously allocated servlet to the pool of available
             * instances.  If this servlet class does not implement SingleThreadModel,
             * no action is actually required.
             *
             * @param servlet The servlet to be returned
             *
             * @exception ServletException if a deallocation error occurs
             */
            @Override
            public void deallocate(Servlet servlet) throws ServletException {
    
                // If not SingleThreadModel, no action is required
                if (!singleThreadModel) {
                    countAllocated.decrementAndGet();
                    return;
                }
    
                // Unlock and free this instance
                //解锁并释放此实例
                synchronized (instancePool) {
                    countAllocated.decrementAndGet();
                    instancePool.push(servlet);
                    instancePool.notify();
                }
    
            }
    

本篇结束,下一篇分析过滤器链相关代码。


来源:https://www.jianshu.com/u/9632919f32c3

点赞(1)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Tomcat源码分析【十五】请求处理过程分析之分配Servlet实例处理请求
上一篇
Tomcat源码分析【十四】请求处理过程分析之Container
下一篇
Tomcat源码分析【十六】请求处理过程分析之创建与执行过滤器链