使用过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. CSharp程序员学Android开发---2.个人总结的快捷键

    最近公司组织项目组成员开发一个Android项目的Demo,之前没有人有Andoid方面的开发经验,都是开发C#的. 虽说项目要求并不是很高,但是对于没有这方面经验的人来说,第一步是最困难的. 项目历 ...

  2. AbpZero之企业微信---登录(拓展第三方auth授权登录)---第一步:查看AbpZero的auth第三方登录的底层机制

    在AbpZero框架中,auth登录接口位于Web.Core库下的Controllers文件夹的TokenAuthController.cs的ExternalAuthenticate方法 Extern ...

  3. 在AbpZero中hangfire后台作业的使用——hangfire的调度

    在abpzero框架中,hangfiire通过依赖注入来进行接口的调用 hangfire的事件处理分为以下几种: 1.基于队列的任务处理(Fire-and-forget jobs) var jobId ...

  4. netcore 发布 到 windows server IIS 可能会报错

    当发布netcore 到windows server iis可能会报这种错:An error occurred while starting the application 不要慌,这个时候可能是你用 ...

  5. C# 实现邮件代发

    由于自己很好奇,有一些推广之类的 邮件,发件人后面,都有一个 由 .... 代发. 所以,查找了一些资料,来验证了一下实现方法. 咱们先来看看,实现代发的 理想效果图 当然,这一种,是利用 代发的 邮 ...

  6. app开发技术调研

    l  面向消费者与公众的应用系统,主要分为3种主流的渠道: 1.   web应用 2.   基于腾讯微信开放api构建的微信app 3.   移动端app ll 在移动端app方面,通过调研,现主流的 ...

  7. 酷!美国国家安全局(NSA)开源了逆向工程工具 Ghidra

    简评:2019 RSA 大会期间,NSA 正式发布了这个工具.免费 + 开源,真的有吸引力,据说体验可以和 IDA 一较高下. Ghidra 是由美国国家安全局(NSA)研究理事会创建和维护的软件逆向 ...

  8. J05-Java IO流总结五 《 BufferedInputStream和BufferedOutputStream 》

    1. 概念简介 BufferedInputStream和BufferedOutputStream是带缓冲区的字节输入输出处理流.它们本身并不具有IO流的读取与写入功能,只是在别的流(节点流或其他处理流 ...

  9. Maven与Hudson集成

    Hudson是一款优秀的持续集成产品,本文阐述Maven于Hudson的集成   Hudson的下载和安装 Hudson有两种安装模式,1:自运行(Hudson内建netty容器),2:放到如tomc ...

  10. IIS Express 配置 Json

    在VS2013中调试D3官网的一些Sample过程中遇到了一个奇怪的问题:凡是Sample中使用的数据源是json文件时候,smaple 就无法在浏览器中正常运行.经调试后发现根本原因是IIS Exp ...