Spring源码分析----DelegatingFilterProxy

  本来是打算写shiro的过滤链是如何处理的,但是它是通过Spring的DelegatingFilterProxy来实现的,所以先得把DelegatingFilterProxy讲清楚。

        顾名思义,DelegatingFilterProxy是一个代理类,代理我们标准的Filter类,并将其委托给一个实现了Filter接口的实例,不同之处在于这个实例是托管到spring中的。好处就很明显了,它可以享受到spring的便利之处,例如在filter类中注入其他的spring bean,更为复杂的初始化逻辑等等。

  既然是托管到了spring中,那么filter的生命周期就交给了spring来管理。但是filter是有自己的生命周期的,DelegatingFilterProxy通过一个名叫targetFilterLifecycle的属性指定是否需要完成filter自己的生命周期方法。

      讲了这么多,先看看DelegatingFilterProxy的庐山真面目:

public class DelegatingFilterProxy extends GenericFilterBean {

    private String contextAttribute;

    private WebApplicationContext webApplicationContext;

    private String targetBeanName;

    private boolean targetFilterLifecycle = false;

    private volatile Filter delegate;

    private final Object delegateMonitor = new Object();

    // 省略了方法
}

属性最重要的就是代理的Filter了,所有的过滤操作都由delegate来实现。webApplicationContext是spring mvc的上下文,delegate需要通过webApplicationContext来获取。targetFilterLifecycle是指明是否需要调用Filter自有的生命周期方法,默认是false。

  大家可以看到DelegatingFilterProxy继承了GenericFilterBean,对于GenericFilterBean,大家只需知道他实现了Filter接口就行了。

  接下来再看看DelegatingFilterProxy有哪些重要的方法:

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

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

  首先是初始化代理的filterBean,如果定义filter的时候给出了targetBeanName,那么则通过webAppliction获取对应的bean,否则根据filterName去获取对应的bean。该方法会在filter的init方法调用时被调用,调用时机在GenericFilterBean里面。在doFilter的时候,则通过调用delegate的doFilter来实现,也就是上面的invokeDelegate()方法。

protected void invokeDelegate(
            Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        delegate.doFilter(request, response, filterChain);
    }

到这里就是很熟悉的Filter调用模式了。

    之前说过,通过代理filter,delegate的生命周期就交给了spring来管理。但是filter是有自己的生命周期的,DelegatingFilterProxy通过一个名叫targetFilterLifecycle的属性指定是否需要完成filter自己的生命周期方法。在bean的创建和销毁时,判断是否需要调用filter的对应的方法。

@Override
    public void destroy() {
        Filter delegateToUse = this.delegate;
        if (delegateToUse != null) {
            destroyDelegate(delegateToUse);
        }
    }

附:代码示例

下载地址:https://download.csdn.net/download/gameloft9/10582213

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/GAMEloft9/article/details/81327492
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞