天天看點

Field redisTemplate in ... required a bean of type ...RedisTemplate' that could not be found.

在springboot整合Redis的時候 ,項目無法啟動,報:

Field redisTemplate in com.xzh.AccessLimitController required a bean of type 'org.springframework.data.redis.core.RedisTemplate' that could not be found.

Field redisTemplate in ... required a bean of type ...RedisTemplate' that could not be found.

我的RedisTemplate注入如下: 

@Autowired
private RedisTemplate<String,Integer> redisTemplate;
           

RedisConfig如下:

@Configuration
@EnableCaching
public class RedisConfig {

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 預設Redis緩存過期時間為1小時50分鐘
        RedisCacheConfiguration redisCacheConfiguration =
                RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofMinutes(110));
        return RedisCacheManager
                .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
                .cacheDefaults(redisCacheConfiguration).build();
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        //使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值(預設使用JDK的序列化方式)
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);

        template.setValueSerializer(serializer);
        //使用StringRedisSerializer來序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(factory);
        return stringRedisTemplate;
    }
           

奇怪的是,不帶泛型的RedisTemplate是可以正常注入的。在網上查找解決方法,發現,将 @Autowired 換成 @Resource 就可以了

@Resource
    private RedisTemplate<String, Integer> redisTemplate;
           

試了一下,果然成功啦。那麼問題來了, @Autowired 和 @Resource 到底有啥差別呢?

請看:@Autowired 和 @Resource 的差別?

因為@Autowired是根據類型來注入的,泛型也被考慮進去了,顯然,我們的RedisTemplate裡并沒有我想要注入的這一類型,是以報錯了;@Resource預設根據名稱注入,redisTemplate 這個bean在我們的RedisConfig裡被加到了spring中,是以是可以被注入的。

既然知道了rootcause,那麼解決方法就很多了,一定要使用@Autowired也是可以的,隻要spring容器中有我們需要的類型的RedisTemple就可以啦:

@Bean
    public RedisTemplate<String, Integer> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Integer> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        //使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值(預設使用JDK的序列化方式)
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(String.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);

        template.setValueSerializer(serializer);
        //使用StringRedisSerializer來序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
           

有的同學可能要說啦,用@Autowired 配合@Qualifier 使用,不也是按名稱注入的嗎,但是忽略了一點是,雖然這樣使用它會按名稱找bean,但是它還是有bean 類型的限制的,看下面的提示就知道啦:

Field redisTemplate in ... required a bean of type ...RedisTemplate' that could not be found.

事實證明,這樣是OK的,是以解決問題最重要的一個環節就是找到造成問題的原因,一旦知道了,解決起來就很簡單了。

繼續閱讀