Spring:代理Filter:DelegatingFilterProxy原理和作用

简介: Spring:代理Filter:DelegatingFilterProxy原理和作用


DelegatingFilterProxy就是一个对于servlet filter的代理,用这个类的好处主要是通过Spring容器来管理servlet filter的生命周期

  • 还有就是如果filter中需要一些Spring容器的实例,可以通过spring直接注入
  • 另外读取一些配置文件这些便利的操作都可以通过Spring来配置实现。


Spring web在设计的时候考虑到某些功能的实现是通过Filter来拦截进行实现的,如果直接的简单的实现几个Filter好像也不是不可以(平时我们就是这么用的),但是Spring框架最核心的是IOC容器,和Spring框架最好的实现就是将要实现的Filter功能注册到IOC容器的一个Bean,这样就可以和Spring IOC容器进行完美的融合,所以Spring Web设计了DelegatingFilterProxy。

本质上来说DelegatingFilterProxy就是一个Filter,其间接实现了Filter接口,但是在doFilter中其实调用的从Spring 容器中获取到的代理Filter的实现类delegate。


DelegatingFilterProxy原理:

1、DelegatingFilterProxy根据targetBeanName从Spring 容器中获取被注入到Spring 容器的Filter实现类,在DelegatingFilterProxy配置时一般需要配置属性targetBeanName

@Override
protected void initFilterBean() throws ServletException {
  synchronized (this.delegateMonitor) {
    if (this.delegate == null) {
      // If no target bean name specified, use filter name.
                        //当Filter配置时如果没有设置targentBeanName属性,则直接根据Filter名称来查找
      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) {
                                //从Spring容器中获取注入的Filter的实现类
        this.delegate = initDelegate(wac);
      }
    }
  }
}
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
    //从Spring 容器中获取注入的Filter的实现类
    Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
    if (isTargetFilterLifecycle()) {
      delegate.init(getFilterConfig());
    }
    return delegate;
  }


2、在DelegatingFilterProxy的实现方法doFilter中,其实最终调用的是委派的类delegate

@Override
protected void initFilterBean() throws ServletException {
  synchronized (this.delegateMonitor) {
    if (this.delegate == null) {
      // If no target bean name specified, use filter name.
                        //当Filter配置时如果没有设置targentBeanName属性,则直接根据Filter名称来查找
      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) {
                                //从Spring容器中获取注入的Filter的实现类
        this.delegate = initDelegate(wac);
      }
    }
  }
}
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
    //从Spring 容器中获取注入的Filter的实现类
    Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);
    if (isTargetFilterLifecycle()) {
      delegate.init(getFilterConfig());
    }
    return delegate;
  }


总结:Spring web通过提高DelegatingProxyFilter类给开发者提供了便利

 

DelegatingFilterProxy运用

需求

在springboot中 使用了filter, 并且注入了业务工具类(APIUtil ),但注入是null

所以问题就来了:springboot中使用filter时注入bean为null的解决办法

其实Spring中,web应用启动的顺序是:listener->filter->servlet,先初始化listener,然后再来就filter的初始化,再接着才到我们的dispathServlet的初始化


解决办法1:

public class TokenAuthFilter implements Filter {
    private final static Logger log = LoggerFactory.getLogger(TokenAuthFilter.class);
    @Autowired
    private APIUtil apiUtil;
}

新增一个config类,用来手工创建filter的bean, 例如:

@Configuration
public class WebConfig {
  @Bean
    public Filter tokenAuthFilter() {
        return new TokenAuthFilter();
    }
    /**
     * 注册filter,统一处理api开头的请求
     * @return FilterRegistrationBean
     */
    @Bean
    public FilterRegistrationBean tokenAuthFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        // DelegatingFilterProxy把servlet 容器中的filter同spring容器中的bean关联起来
        registration.setFilter(new DelegatingFilterProxy("tokenAuthFilter"));
        registration.addUrlPatterns("/api/*");
        registration.setName("tokenAuthFilter");
        registration.setOrder(1);
        return registration;
    }
}


解决办法2:

过滤器是servlet规范中定义的,并不归spring容器管理,也无法直接注入spring中的bean(会报错)

初始化时通过spring上下文获取,进行bean的初始化

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(filterConfig.getServletContext());
    RedisTemplate demoBean = (RedisTemplate)context.getBean("redisTemplate");
    System.out.println(demoBean);
 }

参考链接:https://blog.csdn.net/qq924862077/article/details/81583739 


相关文章
|
3天前
|
安全 前端开发 Java
Spring Boot 过滤器(Filter)详解
本文详解Spring Boot中过滤器的原理与实践,涵盖Filter接口、执行流程、@Component与FilterRegistrationBean两种实现方式、执行顺序控制及典型应用场景如日志记录、权限验证。对比拦截器,突出其在Servlet容器层的通用性与灵活性,助力构建高效稳定的Web应用。
58 0
|
1月前
|
缓存 Java 开发者
【Spring】原理:Bean的作用域与生命周期
本文将围绕 Spring Bean 的作用域与生命周期展开深度剖析,系统梳理作用域的类型与应用场景、生命周期的关键阶段与扩展点,并结合实际案例揭示其底层实现原理,为开发者提供从理论到实践的完整指导。
|
1月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
|
7天前
|
缓存 安全 Java
《深入理解Spring》过滤器(Filter)——Web请求的第一道防线
Servlet过滤器是Java Web核心组件,可在请求进入容器时进行预处理与响应后处理,适用于日志、认证、安全、跨域等全局性功能,具有比Spring拦截器更早的执行时机和更广的覆盖范围。
|
7天前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
15天前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
159 2
|
3天前
|
XML 前端开发 Java
一文搞懂 Spring Boot 自动配置原理
Spring Boot 自动配置原理揭秘:通过 `@EnableAutoConfiguration` 加载 `META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports` 中的配置类,结合 `@Conditional` 按条件注入 Bean,实现“开箱即用”。核心在于约定大于配置,简化开发。
107 0
|
2月前
|
Java 关系型数据库 数据库
深度剖析【Spring】事务:万字详解,彻底掌握传播机制与事务原理
在Java开发中,Spring框架通过事务管理机制,帮我们轻松实现了这种“承诺”。它不仅封装了底层复杂的事务控制逻辑(比如手动开启、提交、回滚事务),还提供了灵活的配置方式,让开发者能专注于业务逻辑,而不用纠结于事务细节。
|
6月前
|
存储 人工智能 自然语言处理
RAG 调优指南:Spring AI Alibaba 模块化 RAG 原理与使用
通过遵循以上最佳实践,可以构建一个高效、可靠的 RAG 系统,为用户提供准确和专业的回答。这些实践涵盖了从文档处理到系统配置的各个方面,能够帮助开发者构建更好的 RAG 应用。
3049 114

热门文章

最新文章