Spring拦截器中@Resource注入为null的问题

Spring拦截器中@Resource注入为null的问题

前言

最近在跟着黑马的视频学SpringBoot项目,遇到了一个很奇怪的问题。在写登录拦截器的时候,明明用了@Resource注解,但是StringRedisTemplate一直是null,调试了好久才找到原因。记录一下这个坑,希望能帮到同样遇到问题的你们。

问题描述

我按照平时的写法,想在拦截器里注入Redis模板:

java 复制代码
@Component
public class LoginInterceptor implements HandlerInterceptor {
    
    @Resource
    private StringRedisTemplate stringRedisTemplate; // 这里一直是null!
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 运行到这里就报空指针异常
        stringRedisTemplate.opsForHash().entries("test");
        return true;
    }
}

配置类是这样写的:

java 复制代码
@Configuration
public class MvcConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor()); // 问题就在这里!
    }
}

为什么会这样?

刚开始我以为是Redis配置有问题,因为在Service层用同样的注解是可以的。问题出在对Spring工作原理的理解上。

Spring依赖注入的条件

Spring只会对它自己管理的Bean进行依赖注入。什么意思呢?

  • 当我写@Component的时候,Spring确实会创建一个LoginInterceptor的Bean
  • 但是在MvcConfig里,我用的是new LoginInterceptor(),这是手动创建的对象
  • 手动创建的对象和Spring管理的Bean是两个不同的实例
  • Spring只会对容器里的那个Bean注入依赖,对手动创建的对象不管

所以就出现了这种情况:

java 复制代码
// Spring容器里有一个LoginInterceptor,StringRedisTemplate被正确注入
LoginInterceptor springBean = 容器中的实例; // stringRedisTemplate ✓

// 我手动创建了另一个LoginInterceptor,Spring不管它
LoginInterceptor myObject = new LoginInterceptor(); // stringRedisTemplate = null ✗

解决方法

方法一:构造函数传参(推荐的方法)

java 复制代码
public class LoginInterceptor implements HandlerInterceptor {
    
    private StringRedisTemplate stringRedisTemplate;
    
    // 通过构造函数接收StringRedisTemplate
    public LoginInterceptor(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 现在可以正常使用了
        stringRedisTemplate.opsForHash().entries("test");
        return true;
    }
}

配置类改成这样:

java 复制代码
@Configuration
public class MvcConfig implements WebMvcConfigurer {
    
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 把StringRedisTemplate传给拦截器
        registry.addInterceptor(new LoginInterceptor(stringRedisTemplate));
    }
}

方法二:注入拦截器Bean

java 复制代码
@Component
public class LoginInterceptor implements HandlerInterceptor {
    
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    
    // 其他代码不变
}

配置类这样写:

java 复制代码
@Configuration
public class MvcConfig implements WebMvcConfigurer {
    
    @Resource // 直接注入Spring管理的LoginInterceptor
    private LoginInterceptor loginInterceptor;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 用注入的实例,不要new
        registry.addInterceptors(loginInterceptor);
    }
}

为什么选择方法一?

为什么不用方法二

  1. 更直观:一看就知道拦截器需要什么依赖
  2. 更灵活 :不需要给拦截器加@Component
  3. 更好测试:写单元测试的时候容易mock
  4. 避免错误:不容易忘记加注解而导致注入失败

确实,构造函数的方式让依赖关系很清楚,代码也更容易理解。

学到的经验

  1. Spring只对自己管理的Bean注入依赖 ,手动new的对象不行
  2. 看到@Resource@Autowired为null,先检查对象是不是Spring管理的
  3. 拦截器、过滤器这些需要手动创建的组件,通过构造函数传依赖比较好
  4. 遇到问题先想想Spring的工作原理,很多问题都能迎刃而解

总结

如果你也遇到了类似的依赖注入问题,可以按这个思路检查:

  1. 这个对象是Spring管理的吗?
  2. 如果不是,怎么让Spring管理它?
  3. 或者换个方式传递依赖?
相关推荐
董董灿是个攻城狮5 分钟前
AI 视觉连载2:灰度图
人工智能
invicinble6 分钟前
对tomcat的提供的功能与底层拓扑结构与实现机制的理解
java·tomcat
较真的菜鸟20 分钟前
使用ASM和agent监控属性变化
java
黎雁·泠崖27 分钟前
【魔法森林冒险】5/14 Allen类(三):任务进度与状态管理
java·开发语言
yunfuuwqi1 小时前
OpenClaw✅真·喂饭级教程:2026年OpenClaw(原Moltbot)一键部署+接入飞书最佳实践
运维·服务器·网络·人工智能·飞书·京东云
九河云1 小时前
5秒开服,你的应用部署还卡在“加载中”吗?
大数据·人工智能·安全·机器学习·华为云
人工智能培训1 小时前
具身智能视觉、触觉、力觉、听觉等信息如何实时对齐与融合?
人工智能·深度学习·大模型·transformer·企业数字化转型·具身智能
wenzhangli71 小时前
能力中心 (Agent SkillCenter):开启AI技能管理新时代
人工智能
后端小肥肠2 小时前
别再盲目抽卡了!Seedance 2.0 成本太高?教你用 Claude Code 100% 出片
人工智能·aigc·agent
每日新鲜事2 小时前
热销复盘:招商林屿缦岛203套售罄背后的客户逻辑分析
大数据·人工智能