@Resource 和 @RequiredArgsConstructor 注入方式不同带来的数据不一致的问题

如标题,这是最近实习遇到的一个bug,当时正编写小程序端的接口,然后把小程序端的登录接口给我写了。

接手时,他的service层使用的是这种方式注入RedisTemplate工具的。

public class Jimmy1{
    @Resource
    private RedisTemplate<String, String> redisTemplate;
}

而我更喜欢使用的注入方式是这样的

@RequiredArgsConstructor
public class Jimmy2{
    private final RedisTemplate<String, String> redisTemplate;
}

因此,我在造登录接口时,沿用他的这个@Resource注解注入的RedisTemplate将相关数据存入redis中。而在我自己的service层中,却使用@RequiredArgsConstructor方式注入的RedisTemplate去取数据。

于是,我的接口就报错了,查了日志。一直觉得自己写的没问题,可是确实是报错了,只能够在每一步都打上一个log.info(""),然后检查方法内每个示例对象是否正确。

经过排查发现。

假设原本的对象数据字符串是 4467,存入redis之后就变成了 "4467" ,使用@Resource的RedisTemplate会自动多加上了一个双引号。

而我自己使用@RequiredArgsConstructor的RedisTemplate,取出数据时却不会把 ""去掉。情况紧急,当时也没发现是注入方式不同引起的问题,于是就将计就计,把取出来的str = str.replaceAll("/"","");去除"引号,接口就正常使用了。。。。

后来逐步定位,才发现是注入方式不同的问题,但是不太确定,昨天加班把接下来两天的工作做完了,今天闲来有时间,就想着真的定位一下问题。

首先,我开了一个demo项目,然后造了两个接口,一个是http://127.0.0.1:8080/redis,一个是http://127.0.0.1:8080/redis/2 ,下方两个图是具体的代码逻辑。

两个controller层中,我使用两种注入方式去注入RedisTemplate示例对象,然后方法中,我把序列化器对象打印在控制台中。发现一个是jdk,一个是string,确实是使用了不一样的序列化器,造成了数据不一致的问题。

具体的getSerializer()方法如下,如下图RedisTemplate类中有一个属性变量为valueSerializer,因此我使用反射的方式获取对应的字段,然后再设置为可访问,然后传入对应的示例对象,获取该对象对应的valueSerializer字段。

    private RedisSerializer<?> getSerializer(RedisTemplate<?, ?> template) throws Exception {
        Field valueSerializerField = RedisTemplate.class.getDeclaredField("valueSerializer");
        valueSerializerField.setAccessible(true);
        return (RedisSerializer<?>) valueSerializerField.get(template);
    }

问题分析出来了,接下来就好解决了。

1.要么就是保证都一起用@Resource注入,要么就是一起用@RequiredArgsConstructor注入,保证注入方式统一。

2.还有一种方式,因为正编在使用RedisTemplate的时候,是没有去配置类设置自定义的序列化器的。(我自己平时直接用StringRedisTemplate的,因此也没有去检查他有没有配置序列化器)那么我们就可以在config配置类使用@Configuration + @Bean的方式自定义序列化器,让springboot不要去选用默认的序列化器,就不会出现选用不同序列化器的问题了。

我自己没在优快云查到对应文章,希望对后来有相同问题的同学有帮助。

我说的是这段代码@Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig { // 新增的依赖字段 private final JwtAuthenticationFilter jwtAuthFilter; private final JwtAuthenticationEntryPoint jwtAuthEntryPoint; private final JwtAccessDeniedHandler jwtAccessDeniedHandler; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .securityMatcher("/api/**") .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(authorize -> authorize .requestMatchers(HttpMethod.POST, "/user/reg_password", "/user/loginPassword") .permitAll() .anyRequest().authenticated() ) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) ) .exceptionHandling(exceptions -> exceptions .authenticationEntryPoint(jwtAuthEntryPoint) .accessDeniedHandler(jwtAccessDeniedHandler) ) .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }出现了The dependencies of some of the beans in the application context form a cycle: ┌─────┐ | jwtAuthenticationFilter defined in file [F:\study\java-code\social-platform\target\classes\com\szx\socialplatform\filter\JwtAuthenticationFilter.class] ↑ ↓ | inMemoryUserDetailsManager defined in class path resource [org/springframework/boot/autoconfigure/security/servlet/UserDetailsServiceAutoConfiguration.class] ↑ ↓ | securityConfig defined in file [F:\study\java-code\social-platform\target\classes\com\szx\socialplatform\config\SecurityConfig.class]
03-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北北叮叮铛铛响

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值