springboot在拦截器中注入bean失败

/ bug / 0 条评论 / 884浏览

springboot在拦截器中注入bean失败

比如,如果我们需要在拦截器中注入redisTempLate,但是我们只重写了添加拦截器,就像这样:

/**
     * TODO 配置redisTemplate
     * Created by zuohui
     **/
    @Bean("redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setKeySerializer(new GenericJackson2JsonRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

/**
     * TODO 注册拦截器
     * Created by zuohui
     **/
    @Bean
    public WebMvcConfigurer apiAutoConfigurer()
    {
        return new WebMvcConfigurer() {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(new VerifyHeaderWhetherInRedisInterceptor())
                        .addPathPatterns("/**");
            }
        };
    }
    
    //当然我们已经编写好了一个名为VerifyHeaderWhetherInRedisInterceptor的拦截器
    public class VerifyHeaderWhetherInRedisInterceptor implements HandlerInterceptor {

    //在这里注入会使null
    @Autowired
    RedisTemplate<Object, Object> redisTemplate;

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

原因:我们注册拦截器的时候是自己重新new了一个,这样等于创建了一个java对象而不是springbean.更重要的是,在spring源码中我们了解到,真实的spring加载bean的过程中会有一些列的执行器,其中有一个就是对springbean进行aop操作的,而这里的@autowire就是通过aop的执行器注入属性的,但是拦截器的初始化是在spring执行aop之前,所以那个时候还没有注入redistemplate,所以就是null

解决方式:

将拦截器注册为springbean,并且直接手动调用

/**
     * TODO 注册拦截器
     * Created by zuohui
     **/
    @Bean
    public WebMvcConfigurer apiAutoConfigurer()
    {
        return new WebMvcConfigurer() {
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(registryMyInterceptor())
                        .addPathPatterns("/**");
            }
        };
    }

    @Bean
    public VerifyHeaderWhetherInRedisInterceptor registryMyInterceptor()
    {
        return new VerifyHeaderWhetherInRedisInterceptor();
    }

这样在@autowire的时候就是可以的了