拦截器中注入(@Autowire/@Resource)对象报空指针异常

正常的拦截类,注入了User。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
public class LoggerInterceptor implements HandlerInterceptor {

//注入user类,注入正常,但是运行时会报空指针异常
@Autowired
private User user;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
user.setName("lucy");
return true;
}
}

正常的添加拦截器的配置,有些人(包括自己)由于不太了解,springboot的底层,经常使用new 一个拦截类添加在配置类中,如下所示。

1
2
3
4
5
6
7
8
9
@Configuration
public class InterceptConfiguration implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
//此处使用new LoggerInterceptor(),并未交给spring管理
registry.addInterceptor(new LoggerInterceptor()).addPathPatterns("/**");
}
}

当运行时,由于在拦截器中注入了User类,会报空指针异常,这是因为我们使用的new LoggerInterceptor(),使我们自己创建的对象,并未交给spring管理。

总共有三种方法解决,总的来说是 new的对象不能调用注入的其他类(即有A,B,C三个类,如果在A中new B(),那么在B中就不能@Autowire C,此时的@Autowire注解失效,拦截器的配置类中new 拦截器,而在拦截器中注入另一个对象,会造成@Autowire失效,出现空指针),所以使用@Autowire注解都使用@Autowire注解,使用new都使用创建对象(会有多例的问题),当然还是推荐使用注解,交给Spring管理。

一种方法:在拦截器中也使用new来创建对象(不推荐)

1
2
3
4
5
6
7
8
9
10
11
12
@Component
public class LoggerInterceptor implements HandlerInterceptor {

//使用new
User user = new User();

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
user.setName("lucy");
return true;
}
}

两种注入的方法:

第一种方法:在拦截器的配置类中使用@Bean,如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Configuration
public class InterceptConfiguration implements WebMvcConfigurer {

/**
*
* SpringBoot的拦截器中依赖注入报空指针问题
*原因:拦截器加载的时间点在springcontext之前,所以在拦截器中注入自然为null ;
*解决方法:配置拦截器链的类中先注入这个拦截器,
*
* @return
*/

@Bean
public LoggerInterceptor loggerInterceptor() {
return new LoggerInterceptor();
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggerInterceptor).addPathPatterns("/**");
}
}

第二种方法:在拦截器的配置类使用@Autowire,如下所示。

1
2
3
4
5
6
7
8
9
10
11
@Configuration
public class InterceptConfiguration implements WebMvcConfigurer {

@Autowired
private LoggerInterceptor loggerInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loggerInterceptor).addPathPatterns("/**");
}
}

总结:new的对象不能调用注入的其他类(即有A,B,C三个类,如果在A中new B(),那么在B中就不能@Autowire C,此时的@Autowire注解失效),所以使用@Autowire注解都使用@Autowire注解,使用new都使用创建对象(会有多例的问题),当然还是推荐使用注解,交给Spring管理。