美文网首页
SpringCache自定义注解, 管理Redis缓存过期时间

SpringCache自定义注解, 管理Redis缓存过期时间

作者: 清蒸三文鱼_ | 来源:发表于2021-02-03 11:24 被阅读0次

    背景

    RedisCacheManager静态管理缓存不够方便, 加上注解支持自定义的缓存过期时间

    Maven

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    

    Code

    配置类

    @EnableCaching
    @Configuration
    @ComponentScan(basePackages = "my.test")
    public class RedisCacheConfig extends CachingConfigurerSupport {
        public static final String EMPTY_KEY = "'DEFAULT'";
        private static final SimpleKeyGenerator SIMPLE_KEY_GENERATOR = new SimpleKeyGenerator();
    
        @Autowired
        private RedisConnectionFactory redisConnectionFactory;
        @Autowired
        private ObjectMapper objectMapper;
        @Autowired
        private ApplicationContext applicationContext;
    
    
        @Override
        @Bean
        public CacheManager cacheManager() {
            Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
            serializer.setObjectMapper(objectMapper);
            RedisSerializationContext.SerializationPair val = RedisSerializationContext.SerializationPair.fromSerializer(serializer);
            RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig()
                    //使用冒号做key的连接符, 默认的是::
                    .computePrefixWith(CacheKeyPrefix.prefixed(":"))
                    .serializeValuesWith(val);
            return RedisCacheManager.builder(redisConnectionFactory)
                    .cacheDefaults(defaultCacheConfig)
                    .withInitialCacheConfigurations(initRedisCacheConfig(val)).build();
        }
    
        public HashMap<String, RedisCacheConfiguration> initRedisCacheConfig(RedisSerializationContext.SerializationPair ser) {
            HashMap<String, RedisCacheConfiguration> cacheConfigMap = new HashMap<>();
            for (String bean : applicationContext.getBeanNamesForType(Object.class)) {
                Class<?> clazz = applicationContext.getType(bean);
                if (Objects.isNull(clazz)) {
                    continue;
                }
                ReflectionUtils.doWithMethods(clazz, method -> {
                    ReflectionUtils.makeAccessible(method);
                    method.getAnnotation(CacheExpire.class);
                    CacheExpire cacheExpire = AnnotationUtils.findAnnotation(method, CacheExpire.class);
                    if (Objects.isNull(cacheExpire)) {
                        return;
                    }
    
                    Cacheable cacheable = AnnotationUtils.findAnnotation(method, Cacheable.class);
                    if (Objects.nonNull(cacheable)) {
                        for (String cacheName : cacheable.cacheNames()) {
                            if (StringUtils.isEmpty(cacheName)) {
                                continue;
                            }
                            RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                                    .entryTtl(Duration.ofMillis(cacheExpire.type().toMillis(cacheExpire.expire())))
                                    .disableCachingNullValues().serializeValuesWith(ser);
                            cacheConfigMap.put(cacheName, config);
                        }
                    }
                });
            }
            return cacheConfigMap;
        }
    
        @Override
        @Bean
        public KeyGenerator keyGenerator() {
            return (o, m, params) -> {
                CacheEvict cacheEvict = m.getAnnotation(CacheEvict.class);
                if (Objects.nonNull(cacheEvict) && EMPTY_KEY.equals(cacheEvict.key())) {
                    return EMPTY_KEY;
                }
                if (params.length == 0) {
                    return EMPTY_KEY;
                }
                return SIMPLE_KEY_GENERATOR.generate(o, m, params);
            };
        }
    }
    

    入口类

    @EnableCaching
    @SpringBootApplication
    public class App {
        public static void main(String[] args) {
            SpringApplication.run(App.class, args);
        }
    
        @Component
        class CacheRun implements CommandLineRunner {
            @Autowired
            TestService testService;
            @Autowired
            RedisTemplate<String, String> redisTemplate;
    
            @Override
            public void run(String... args) throws Exception {
                {
                    HashMap<String, Object> d1 = testService.get();
                    Thread.sleep(8000);
                    String val = redisTemplate.opsForValue().get("get::DEFAULT");
                    assert val == null;
                }
            }
        }
    }
    

    注解类

    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface CacheExpire {
        @AliasFor("expire")
        long value() default 60L;
    
        @AliasFor("value")
        long expire() default 60L;
    
        TimeUnit type() default TimeUnit.SECONDS;
    }
    

    测试类

    @Service
    public class TestService {
        HashMap<String, Object> data = new HashMap<>();
        {
            data.put("1", "1_x");
            data.put("2", "2_x");
        }
    
        @Cacheable(value = "get", key = EMPTY_KEY)
        @CacheExpire(value = 5)
        public HashMap<String, Object> get() {
            return data;
        }
    }
    

    相关文章

      网友评论

          本文标题:SpringCache自定义注解, 管理Redis缓存过期时间

          本文链接:https://www.haomeiwen.com/subject/xgpptltx.html