DelegatingFilterProxy分析

前言

最近在分析源碼時發現了一個配置以下:web

#web.xml文件中
<filter>
    <filter-name>cacheSessionFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-vale>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name></filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

#applicationContext.xml文件
<bean name="cacheSessionFilter"  class="xxxx.xxx.xxFilter"/>

那麼這個DelegatingFilterProxy究竟是幹嗎用的那???網上查了不少,最終總結爲一句話即:DelegateFilterProxy實現了服務器容器(tomcate was等)中的filter調用spring容器中類的功能,那這是如何實現的那?spring

DelegatingFilterProxy和spring容器如何關聯的?

觀察web.xml文件,spring的初始化通常都是在很是靠前的,也就是說在使用delegatingfilterproxy以前,spring容器已經初始化完成了,而後觀察delegatingfilterproxy的源碼會發現有這麼一段tomcat

protected void initFilterBean() throws ServletException {
        synchronized (this.delegateMonitor) {
            if (this.delegate == null) {
                // If no target bean name specified, use filter name.
                if (this.targetBeanName == null) {
                    this.targetBeanName = getFilterName();
                }
                // Fetch Spring root application context and initialize the delegate early,
                // if possible. If the root application context will be started after this
                // filter proxy, we'll have to resort to lazy initialization.
                WebApplicationContext wac = findWebApplicationContext();
                if (wac != null) {
                    this.delegate = initDelegate(wac);
                }
            }
        }
    }

沒錯WebApplicationContext其實就是spring容器,也就是說DelegatingFilterProxy中保存有spring的容器,而在WebApplicationContext中有一個和DelegatingFilerProxy同名的類(這個類就是咱們本身的類),DelegatingFilterProxy會從WebApplicationContext中尋找那個和其同名的類,而後將全部的動做賦予給它。服務器

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        // Lazily initialize the delegate if necessary.
        Filter delegateToUse = this.delegate;
        if (delegateToUse == null) {
            synchronized (this.delegateMonitor) {
                delegateToUse = this.delegate;
                if (delegateToUse == null) {
                    WebApplicationContext wac = findWebApplicationContext();
                    if (wac == null) {
                        throw new IllegalStateException("No WebApplicationContext found: " +
                                "no ContextLoaderListener or DispatcherServlet registered?");
                    }
                    delegateToUse = initDelegate(wac);
                }
                this.delegate = delegateToUse;
            }
        }

        // Let the delegate perform the actual doFilter operation.
        invokeDelegate(delegateToUse, request, response, filterChain);
    }

其中的delegateToUse就是從webapplicationcontext中取出來的:app

@Override
    protected void initFilterBean() throws ServletException {
        synchronized (this.delegateMonitor) {
            if (this.delegate == null) {
                // If no target bean name specified, use filter name.
                if (this.targetBeanName == null) {
                    this.targetBeanName = getFilterName();
                }
                // Fetch Spring root application context and initialize the delegate early,
                // if possible. If the root application context will be started after this
                // filter proxy, we'll have to resort to lazy initialization.
                WebApplicationContext wac = findWebApplicationContext();
                if (wac != null) {
                    this.delegate = initDelegate(wac);
                }
            }
        }
    }
相關文章
相關標籤/搜索