zoukankan      html  css  js  c++  java
  • spring之DelegatingFilterProxy

    DelegatingFilterProxy是一个标准servlet Filter的代理,代理实现了Filter接口的spring管理的Bean。支持一个在web.xml的init-param定义的"targetBeanName" filter,在spring applicationContext中指定了target bean的名称。

    web.xml通常包含一个DelegatingFilterProxy的定义,它在root springContext中指定了filter-name及对应的bean。在springcontext中实现了标准servlet filter接口的bean在调用时都将被代理。

       注意:Servlet Filter接口默认定义的lifecycle方法不会被代理到target bean,它依赖spring applicationContext管理target bean的lifecycle。在filter的属性targetFilterLifecycle的init-param中指定为true将强制执行Filter.init()和Filter.destory()方法,让Filter来管理filter的lifecycle。

     从spring 3.1开始,DelegatingFilterProxy更新到可以支持servlet 3.0基于实例的filter注册方法来构建,通常和spring 3.1的 org.springframework.web.WebApplicationInitializer spi一起使用。这个类由spring security中Ben Alex 写的FilterToBeanProxy灵感触发而写的。

    具体实现如下:

    1.初始化方法

        @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);
                    }
                }
            }
        }

    初始化代理

        /**
         * Initialize the Filter delegate, defined as bean the given Spring
         * application context.
         * <p>The default implementation fetches the bean from the application context
         * and calls the standard {@code Filter.init} method on it, passing
         * in the FilterConfig of this Filter proxy.
         * @param wac the root application context
         * @return the initialized delegate Filter
         * @throws ServletException if thrown by the Filter
         * @see #getTargetBeanName()
         * @see #isTargetFilterLifecycle()
         * @see #getFilterConfig()
         * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
         */
        protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
            Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
            if (isTargetFilterLifecycle()) {
                delegate.init(getFilterConfig());
            }
            return delegate;
        }

    2. 触发代理方法

        @Override
        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) {
                    if (this.delegate == null) {
                        WebApplicationContext wac = findWebApplicationContext();
                        if (wac == null) {
                            throw new IllegalStateException("No WebApplicationContext found: " +
                                    "no ContextLoaderListener or DispatcherServlet registered?");
                        }
                        this.delegate = initDelegate(wac);
                    }
                    delegateToUse = this.delegate;
                }
            }
    
            // Let the delegate perform the actual doFilter operation.
            invokeDelegate(delegateToUse, request, response, filterChain);
        }

    触发代理

        /**
         * Actually invoke the delegate Filter with the given request and response.
         * @param delegate the delegate Filter
         * @param request the current HTTP request
         * @param response the current HTTP response
         * @param filterChain the current FilterChain
         * @throws ServletException if thrown by the Filter
         * @throws IOException if thrown by the Filter
         */
        protected void invokeDelegate(
                Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {
    
            delegate.doFilter(request, response, filterChain);
        }

    3.销毁方法

        /**
         * Destroy the Filter delegate.
         * Default implementation simply calls {@code Filter.destroy} on it.
         * @param delegate the Filter delegate (never {@code null})
         * @see #isTargetFilterLifecycle()
         * @see javax.servlet.Filter#destroy()
         */
        protected void destroyDelegate(Filter delegate) {
            if (isTargetFilterLifecycle()) {
                delegate.destroy();
            }
        }
  • 相关阅读:
    int和Integer有什么区别
    互联网思维的四个核心观点九大思维解读
    未来流行的12种商业模式
    小黑裙三级分销模式
    数据库设计三大范式
    数据库设计中常见表结构的设计技巧
    软件架构的演进,了解单体架构,垂直架构,SOA架构和微服务架构的变化历程
    查理芒格的25种人类误判心理学
    聪明的老板,都懂得让人占便宜(经典)
    真正聪明的人,从不占人便宜
  • 原文地址:https://www.cnblogs.com/davidwang456/p/6511443.html
Copyright © 2011-2022 走看看