[转]springSecurity源码分析—DelegatingFilterProxy类的作用

使用过springSecurity的朋友都知道,首先需要在web.xml进行以下配置,

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

<init-param>

        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>  <!-- 默认是false -->
    </init-param>

</filter>

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>

</filter-mapping>

从这个配置中,可能会给我们造成一个错觉,以为DelegatingFilterProxy类就是springSecurity的入口,但其实这个类位于spring-web-3.0.5.RELEASE.jar这个jar下面,说明这个类本身是和springSecurity无关。DelegatingFilterProxy类继承于抽象类GenericFilterBean,间接地implement 了javax.servlet.Filter接口,Servlet容器在启动时,首先会调用Filter的init方法,GenericFilterBean的作用主要是可以把Filter的初始化参数自动地set到继承于GenericFilterBean类的Filter中去。在其init方法的如下代码就是做了这个事:


1

2

3

4

5

6

PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);

BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);

ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());

bw.registerCustomEditor(Resource.classnew ResourceEditor(resourceLoader));

initBeanWrapper(bw);

bw.setPropertyValues(pvs, true);

另外在init方法中调用了initFilterBean()方法,该方法是GenericFilterBean类是特地留给子类扩展用的,


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

protected void initFilterBean() throws ServletException {

        // 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.

        synchronized (this.delegateMonitor) {

            WebApplicationContext wac = findWebApplicationContext();

            if (wac != null) {

                this.delegate = initDelegate(wac);

            }

        }

    }

可以看出上述代码首先看Filter是否提供了targetBeanName初始化参数,如果没有提供则直接使用filter的name做为beanName,产生了beanName后,由于我们在web.xml的filter的name是springSecurityFilterChain,从spring的IOC容器中取出bean的代码是initDelegate方法,下面是该方法代码:


1

2

3

4

5

6

7

protected Filter initDelegate(WebApplicationContext wac) throws ServletException {

        Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);

        if (isTargetFilterLifecycle()) {

            delegate.init(getFilterConfig());

        }

        return delegate;

}

通过跟踪代码,发现取出的bean是org.springframework.security.FilterChainProxy,该类也是继承于GenericFilterBean,取出bean后,判断targetFilterLifecycle属性是false还是true,决定是否调用该类的init方法。这个FilterChainProxy bean实例最终被保存在DelegatingFilterProxy类的delegate属性里,

下面看一下DelegatingFilterProxy类的doFilter方法


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)

            throws ServletException, IOException {

        // Lazily initialize the delegate if necessary.

        Filter delegateToUse = null;

        synchronized (this.delegateMonitor) {

            if (this.delegate == null) {

                WebApplicationContext wac = findWebApplicationContext();

                if (wac == null) {

                    throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");

                }

                this.delegate = initDelegate(wac);

            }

            delegateToUse = this.delegate;

        }

        // Let the delegate perform the actual doFilter operation.

        invokeDelegate(delegateToUse, request, response, filterChain);

    }

真正要关注invokeDelegate(delegateToUse, request, response, filterChain);这句代码,在下面可以看出DelegatingFilterProxy类实际是用其delegate属性即org.springframework.security.FilterChainProxy实例的doFilter方法来响应请求。


1

2

3

4

5

6

protected void invokeDelegate(

            Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)

            throws ServletException, IOException {

        delegate.doFilter(request, response, filterChain);

    }

以上就是DelegatingFilterProxy类的一些内部运行机制,其实主要作用就是一个代理模式的应用,可以把servlet 容器中的filter同spring容器中的bean关联起来。

此外还要注意一个DelegatingFilterProxy的一个初始化参数:targetFilterLifecycle ,其默认值为false 。 但如果被其代理的filter的init()方法和destry()方法需要被调用时,需要设置targetFilterLifecycle为true。具体可见DelegatingFilterProxy中的如下代码:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

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

                }

            }

        }

    }

protected Filter initDelegate(WebApplicationContext wac) throws ServletException {

        Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);

        if (isTargetFilterLifecycle()) {    //注意这行

            delegate.init(getFilterConfig());

        }

        return delegate;

    }

(原文地址:http://www.cnblogs.com/hzhuxin/archive/2011/12/19/2293730.html)

时间: 2024-12-20 18:52:53

[转]springSecurity源码分析—DelegatingFilterProxy类的作用的相关文章

AppWidget源码分析---接口类

最近项目中接触到AppWidget,相对来说这部分比较简单,所以趁着空余时间详细阅读了AppWidget的源码.这篇文章主要是从源码上分析AppWidget中API类的相关原理,相关类的简单功能介绍和实现原理.关于使用,建议看指导文档. 简述 AppWidget相关的API类(供我们应用开发者使用的类)主要有: AppWidgetProvider:继承这个类,来提供Appwidget. AppWidgetManager:提供了AppWidget的管理接口,比如更新,绑定AppWidget id,

Struts2 源码分析——Result类实例

本章简言 上一章笔者讲到关于DefaultActionInvocation类执行action的相关知识.我们清楚的知道在执行action类实例之后会相关处理返回的结果.而这章笔者将对处理结果相关的内容进行讲解.笔者叫他们为Result类实例.如果还记得在上一章最后笔者说可以把处理action执行的结果简单的理解处理网页.而且还用红色标识.实际是处理跟表现层有关的内容.而不是页面上的内容.如HTML.即是MVC里面的C到V的内容.当然这还关系到配置文件里面的result元素节点信息.如strtus

tornado框架源码分析---Application类之debug参数

先贴上Application这个类的源码. class Application(httputil.HTTPServerConnectionDelegate): """A collection of request handlers that make up a web application. Instances of this class are callable and can be passed directly to HTTPServer to serve the a

Threadlocal源码分析以及其中WeakReference作用分析

今天在看Spring 3.x企业应用开发实战,第九章 Spring的事务管理,9.2.2节ThreadLocal的接口方法时,书上有提到Threadlocal的简单实现,我就去看了下JDK1.8的Threadlocal的源码.发现实现方式与书中讲的并不相同,同时在网上搜索了一下,发现有比较多的人理解错了. 先看一下容易误导的解释:在ThreadLocal类中有一个Map对象,这个Map以每个Thread对象为键,保存了这个线程对应局部变量值,对应的实现方式如下: public class Sim

yii2 源码分析 Action类分析 (六)

Action类是控制器的基类, <?php namespace yii\base; use Yii; /** * Action是所有控制器动作类的基类,它继承组件类 * * 动作提供了重用动作方法代码的方法, * Action类中的动作方法可以用于多个控制器或不同的项目中. * * 派生类必须实现一个方法叫` run() ` * 当请求操作时,该方法将由控制器调用 * `run()` 方法的参数由用户根据他们的名字自动输入的值确定 * 例如, `run()`方法以以下形式定义 * * ```ph

yii2 源码分析Action类分析 (六)

Action类是控制器的基类, <?php namespace yii\base; use Yii; /** * Action是所有控制器动作类的基类,它继承组件类 * * 动作提供了重用动作方法代码的方法, * Action类中的动作方法可以用于多个控制器或不同的项目中. * * 派生类必须实现一个方法叫` run() ` * 当请求操作时,该方法将由控制器调用 * `run()` 方法的参数由用户根据他们的名字自动输入的值确定 * 例如, `run()`方法以以下形式定义 * * ```ph

yii2 源码分析 model类分析 (五)

模型类是数据模型的基类.此类继承了组件类,实现了3个接口 先介绍一下模型类前面的大量注释说了什么: * 模型类是数据模型的基类.此类继承了组件类,实现了3个接口 * 实现了IteratorAggregate(聚合式迭代器)接口,实现了ArrayAccess接口,可以像数组一样访问对象,这两个接口是php自带 * Arrayable接口是yii2框架自带 * 模型实现了以下常用功能: * * - 属性声明: 默认情况下,每个公共类成员都被认为是模型属性 * - 属性标签: 每个属性可以与用于显示目

yii2 源码分析Behavior类分析 (四)

Behavior类是所有事件类的基类,它继承自object类 Behavior类的前面注释描述大概意思: * Behavior类是所有事件类的基类 * * 一个行为可以用来增强现有组件的功能,而不需要修改它的代码. * 用来增强现有组件的功能而不修改它的代码.它可以添加自己的方法和属性组件 * 使他们可以直接通过组件访问.还可以响应组件触发的事件,拦截正常的代码执行. class Behavior extends Object { /** * 要附加行为对象的组件 */ public $owne

yii2 源码分析 Component类分析 (二)

转载请注明链接http://www.cnblogs.com/liuwanqiu/p/6739538.html 组件(component),是Yii框架的基类,实现了属性.事件.行为三类功能,它集成自object类 类前面的大部分注释: 1.事件在定义的类中唯一名称标示,事件名称区分大小写 2.将事件处理程序到附加到事件,是用on 3.有三种事件函数的调用方法,匿名函数调用,对象调用,静态方法调用,全局函数调用 4.可以在配置中配置组件,使用方式是: [ 'on add' => function