SpringBoot--Spring MVC 拦截器注入与 new 的区别
1️⃣ 核心概念
Spring MVC 的拦截器(
HandlerInterceptor
)可以用两种方式注册:
由 Spring 管理的 Bean 注入
通过
@Component
或@Bean
注入拦截器内部可以使用
@Autowired
注入其他 Bean直接 new 一个对象
拦截器内部不依赖 Spring Bean,完全自给自足
不会触发 Spring 的依赖注入和生命周期管理
什么时候用哪个?
3.1.拦截器需要依赖注入的情况
如果拦截器中需要通过
@Autowired
注入属性,例如:@Component public class TokenIntercept implements HandlerInterceptor {@Autowiredprivate RedisTemplate redisTemplate; }
则拦截器类必须加上
@Component
,由 Spring 容器管理。在
WebMvcConfigurer
中必须通过@Autowired
注入该拦截器:@Autowired private TokenIntercept tokenIntercept;
如果使用
new TokenIntercept()
直接创建实例,拦截器内部的redisTemplate
将会是null
,依赖注入无法生效。3.2.拦截器不依赖注入的情况
如果拦截器内部不需要通过
@Autowired
注入属性,则类上加不加@Component
都可以。
在
WebMvcConfigurer
中可以通过@Autowired
注入,也可以直接new
实例:registry.addInterceptor(new LoginInterceptor());
因为拦截器内部没有依赖注入的属性,所以无论 Spring 管理与否,都不会影响拦截器的功能。
2️⃣ 为什么要注意这个区别?
情况 方法 原因 拦截器内部需要注入其他 Bean(Redis、JWT、Service 等) 通过 Spring 注入 ( @Component
+@Autowired
)直接 new
拦截器不会触发依赖注入,内部对象为 null拦截器内部不需要依赖 Bean 可以直接 new
简单轻量,不依赖 Spring 管理 💡 关键点:是否依赖 Spring 注入决定能否直接 new。
3️⃣ 例子对比
3.1 通过 Spring 注入
@Component public class TokenIntercept implements HandlerInterceptor {@Autowiredprivate RedisUtil redisUtil;@Autowiredprivate JwtUtil jwtUtil;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {System.out.println("拦截器拦截请求");String token = request.getHeader("token");if (token == null) return false;String userId = jwtUtil.parseJWT(token);String redisToken = (String) redisUtil.get("token:userId:" + userId);return token.equals(redisToken);} }@Configuration public class TokenInterceptConfig implements WebMvcConfigurer {@Autowiredprivate TokenIntercept tokenIntercept; // 注入 Spring 管理的 Bean@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(tokenIntercept).excludePathPatterns("/login/**","/register/**").addPathPatterns("/**");} }
✅ 特点:
TokenIntercept
内部依赖RedisUtil
和JwtUtil
必须通过
@Autowired
注入,不能new
3.2 直接 new 对象
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {System.out.println("登录拦截器拦截请求");return true;} }@Configuration public class MvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()) // 直接 new.excludePathPatterns("/login/**", "/register/**");} }
✅ 特点:
拦截器内部没有依赖 Spring Bean
直接
new
就可以使用生命周期由程序管理,Spring 不会干预
4️⃣ 总结
是否依赖注入 决定拦截器是否可以直接 new:
依赖注入 → 必须通过 Spring 容器管理
不依赖 → 可直接 new
注意事项:
如果直接 new,会导致拦截器内部的
@Autowired
失效Spring 管理的 Bean 可以享受 AOP、事务、依赖注入等功能
最佳实践:
推荐:所有需要依赖注入的拦截器都使用 Spring 容器管理
简单拦截器(如日志、统计、权限判断)可以直接 new