public void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        Exception exception = null;

        try {

            boolean continueChain = preHandle(request, response);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Invoked preHandle method.  Continuing chain?: [" + continueChain + "]");
            }

            if (continueChain) {
                executeChain(request, response, chain);
            }

            postHandle(request, response);
            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Successfully invoked postHandle method");
            }

        } catch (Exception e) {
            exception = e;
        } finally {
            cleanup(request, response, exception);
        }
    }
Actually implements the chain execution logic, utilizing
{@link #preHandle(javax.servlet.ServletRequest, javax.servlet.ServletResponse) pre},
{@link #postHandle(javax.servlet.ServletRequest, javax.servlet.ServletResponse) post}, and
{@link #afterCompletion(javax.servlet.ServletRequest, javax.servlet.ServletResponse, Exception) after}
advice hooks.

@param request  the incoming ServletRequest
@param response the outgoing ServletResponse
@param chain    the filter chain to execute
@throws ServletException if a servlet-related error occurs
@throws IOException      if an IO error occurs
web/src/main/java/org/apache/shiro/web/servlet/AdviceFilter.java