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

  1. <filter>
  2. <filter-name>springSecurityFilterChain</filter-name>
  3. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  4. <init-param>
  5. <param-name>targetFilterLifecycle</param-name>
  6. <param-value>true</param-value>  <!-- 默认是false -->
  7. </init-param>
  8. </filter>
  9. <filter-mapping>
  10. <filter-name>springSecurityFilterChain</filter-name>
  11. <url-pattern>/*</url-pattern>
  12. </filter-mapping>

非springSecurity用法如下:

  1. <filter>
  2. <filter-name>DelegatingFilterProxy</filter-name>
  3. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  4. <init-param>
  5. <param-name>targetBeanName</param-name>
  6. <!-- 自定义filter -->
  7. <param-value>exportExamineFilter</param-value>
  8. </init-param>
  9. <init-param>
  10. <!-- 判断targetFilterLifecycle属性是false还是true,决定是否调用自定义类的init()、destry()方法 -->
  11. <param-name>targetFilterLifecycle</param-name>
  12. <param-value>false</param-value>
  13. </init-param>
  14. </filter>
  15. <filter-mapping>
  16. <filter-name>DelegatingFilterProxy</filter-name>
  17. <url-pattern>/*</url-pattern>
  18. </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. PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);
  2. BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
  3. ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());
  4. bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader));
  5. initBeanWrapper(bw);
  6. bw.setPropertyValues(pvs, true);

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

  1. protected void initFilterBean() throws ServletException {
  2. // If no target bean name specified, use filter name.
  3. if (this.targetBeanName == null) {
  4. this.targetBeanName = getFilterName();
  5. }
  6. // Fetch Spring root application context and initialize the delegate early,
  7. // if possible. If the root application context will be started after this
  8. // filter proxy, we'll have to resort to lazy initialization.
  9. synchronized (this.delegateMonitor) {
  10. WebApplicationContext wac = findWebApplicationContext();
  11. if (wac != null) {
  12. this.delegate = initDelegate(wac);
  13. }
  14. }
  15. }

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

  1. protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
  2. Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
  3. if (isTargetFilterLifecycle()) {
  4. delegate.init(getFilterConfig());
  5. }
  6. return delegate;
  7. }

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

下面看一下DelegatingFilterProxy类的doFilter方法

  1. public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
  2. throws ServletException, IOException {
  3. // Lazily initialize the delegate if necessary.
  4. Filter delegateToUse = null;
  5. synchronized (this.delegateMonitor) {
  6. if (this.delegate == null) {
  7. WebApplicationContext wac = findWebApplicationContext();
  8. if (wac == null) {
  9. throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
  10. }
  11. this.delegate = initDelegate(wac);
  12. }
  13. delegateToUse = this.delegate;
  14. }
  15. // Let the delegate perform the actual doFilter operation.
  16. invokeDelegate(delegateToUse, request, response, filterChain);
  17. }

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

  1. protected void invokeDelegate(
  2. Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
  3. throws ServletException, IOException {
  4. delegate.doFilter(request, response, filterChain);
  5. }

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

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

  1. protected void initFilterBean() throws ServletException {
  2. synchronized (this.delegateMonitor) {
  3. if (this.delegate == null) {
  4. // If no target bean name specified, use filter name.
  5. if (this.targetBeanName == null) {
  6. this.targetBeanName = getFilterName();
  7. }
  8. // Fetch Spring root application context and initialize the delegate early,
  9. // if possible. If the root application context will be started after this
  10. // filter proxy, we'll have to resort to lazy initialization.
  11. WebApplicationContext wac = findWebApplicationContext();
  12. if (wac != null) {
  13. this.delegate = initDelegate(wac);
  14. }
  15. }
  16. }
  17. }
  18. protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
  19. Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
  20. if (isTargetFilterLifecycle()) {    //注意这行
  21. delegate.init(getFilterConfig());
  22. }
  23. return delegate;
  24. }

DelegatingFilterProxy类的作用的更多相关文章

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

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

  2. C++虚基类的作用

    虚基类的作用     当一个基类被声明为虚基类后,即使它成为了多继承链路上的公共基类,最后的派生类中也只有它的一个备份.例如:class CBase { }:class CDerive1:virtua ...

  3. dubbo源码分析4——SPI机制_ExtensionFactory类的作用

    ExtensionFactory的源码: @SPI public interface ExtensionFactory { /** * Get extension. * * @param type o ...

  4. 关于struts2中ActionContext类的作用

    关于struts2中ActionContext类的作用有三个: 1.获取三大作用域对象及页面参数 2.是struts标签的上下文对象 3.ThreadLocal内装的就是ActionContext 怎 ...

  5. JAVA基础加强(张孝祥)_类加载器、分析代理类的作用与原理及AOP概念、分析JVM动态生成的类、实现类似Spring的可配置的AOP框架

    1.类加载器 ·简要介绍什么是类加载器,和类加载器的作用 ·Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader ...

  6. Java中Class和单例类的作用与类成员的理解

    Java中Class类的作用与深入理解 在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识.这个信息跟踪着每个对象所属的类.JVM利用运行时信息选择相应的方法执行.而保存 ...

  7. 【转载】C#中SqlCommand类的作用以及常用方法

    在C#的数据库操作过程中,SqlCommand类一般用于Sqlserver数据库的SQL语句的执行,包括Select语句.Update语句.Delete语句以及SQL存储过程等,SqlCommand的 ...

  8. 【转载】C#中SqlConnection类的作用以及常用方法

    在C#的数据库编程中,SqlConnection类主要用于连接Sqlserver数据库,使用SqlConnection类的实例方法我们可以打开Sqlserver数据库连接以及获取数据完毕后关闭数据库连 ...

  9. servlet过滤器Filter使用之DelegatingFilterProxy类

    正常情况下,我们需要添加一个过滤器,需要实现javax.servlet.Filter接口,再在web.xml中配置filter,如下: package cc.eabour.webapp.securit ...

随机推荐

  1. SQL分组合并

    STUFF ( character_expression , start , length ,character_expression ) select TcodMedInst_GUID,stuff( ...

  2. K8S+GitLab-自动化分布式部署ASP.NET Core(二) ASP.NET Core DevOps

    一.介绍 前一篇,写的K8S部署环境的文章,简单的介绍下DevOps(Development和Operations的组合词),高效交付, 自动化流程,来减少软件开发人员和运维人员的沟通.Martin ...

  3. Oracle数据库设置Scott登录

    Oracle数据库Scott登录 在安装数据库时,用户登录选项中,Scott用户默认是未解锁的. 用户名填写as sysdba:密码是原来设置的,登录进去,新建SQL窗口,输入命令: alert us ...

  4. reids 安装

    第一步:在VMware中安装CentOS(参考Linux教程中的安装虚拟机) 第二步:在Linux下安装gcc环境 [root@hadoop ~]#yum install gcc-c++ 第三步:将下 ...

  5. 敏捷项目-依赖项拖动change

    1. 2.类方法插入数据.

  6. python del 方法的使用

    在Python 的自带函数中 del 函数是一个非常特殊但是又非常使用的函数 my_list = [1,2,3] my_dict = {"name":"lowman&qu ...

  7. webpack快速入门——CSS进阶:SASS文件的打包和分离

    1.安裝:因为sass-loader依赖于node-sass,所以需要先安装node-sass cnpm install node-sass --save-dev cnpm install sass- ...

  8. PHP之旅4 php 超全局变量

    预定义数组: 自动全局变量---超全局数组 1.包含了来自web服务器,客户端,运行环境和用户输入的数据 2.这些数组比较特别 3.全局范围内自动生效,都可以直接使用这些数组 4.用户不能自定义这些数 ...

  9. thuwc2019总结

    275,是我的自己的估分 而350,是面试线 就发挥而言,这次的发挥相当糟糕,第一天选择全场打暴力而不打签到题正解,第二天因A题思路想偏造成2h额外时间花费.第二题与第三题之间,我选择了难打的第三题而 ...

  10. POJ 1023

    #include <iostream> #include <string> #include <cmath> #define MAXN 65 int op[MAXN ...