zoukankan      html  css  js  c++  java
  • 利用反射注册SpringCache的RedisCacheManager缓存信息

    项目开发中,SpringCache是一个非常方便的工具,但是在配置信息注册时,用枚举方式可以满足遍历,但却无法应用在@Cacheable注解里,因此可以通过静态类的方式,借助反射完成缓存信息注册。

    配置类如下:

    package com.zora.cloud.demo.config;
    
    import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.cache.RedisCacheConfiguration;
    import org.springframework.data.redis.cache.RedisCacheManager;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.serializer.RedisSerializationContext;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    import java.lang.reflect.Field;
    import java.time.Duration;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * <h3>metaapp-gamex</h3>
     * <h4>com.metaapp.cloud.gamex.config</h4>
     * <p>SpringCache配置</p>
     *
     * @author Yuhan.Ji
     * @since 2020.03.23
     */
    @Slf4j
    @Configuration
    public class CacheConfig {
        private String appName = "Demo";
        /**
         * 当没有配置缓存失效时间情况下的默认ttl
         */
        public static final int DEFAULT_EXPIRE_SECOND = 180;
    
        // 用于SpringBoot 2.0和2.1的配置方式
        @Bean
        public RedisCacheManager builder(RedisConnectionFactory factory) {
            try {
                // 这里的参数填充对应的静态属性类
                Map<String, Integer> configMap = ReflectUtil.getCacheTtlConfigMap(Constants.class);
                RedisCacheManager.RedisCacheManagerBuilder builder = RedisCacheManager.RedisCacheManagerBuilder
                        .fromConnectionFactory(factory);
                if (!configMap.isEmpty()) {
                    Map<String, RedisCacheConfiguration> configurationMap = new HashMap<>();
                    for (String cacheName : configMap.keySet()) {
                        configurationMap.
                                put(cacheName, RedisCacheConfiguration
                                        .defaultCacheConfig()
                                        .computePrefixWith(name -> appName + ":" + name + ":")
                                        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericFastJsonRedisSerializer()))
                                        .entryTtl(Duration.ofSeconds(configMap.get(cacheName))));
                    }
                    builder.withInitialCacheConfigurations(configurationMap);
                    log.info("MetaApp Spring Cache Redis : 缓存配置为:{}", configMap.toString());
                }
                return builder.build();
            } catch (IllegalAccessException illegalEx) {
                log.error("SpringCache RedisCacheManagerBuilderCustomizer配置失败,启动终止。请检查RedisCacheManagerBuilder类中ReflectUtil.getCacheTtlConfigMap()部分", illegalEx);
                System.exit(500);
                return null;
            }
        }
    
    //    // 用于SpringBoot 2.2 的配置方式
    //    @Bean
    //    public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
    //        return builder -> {
    //            try {
    //                // 这里的参数填充对应的静态属性类
    //                Map<String, Integer> configMap = ReflectUtil.getCacheTtlConfigMap(Constants.class);
    //                if (!configMap.isEmpty()) {
    //                    Map<String, RedisCacheConfiguration> configurationMap = new HashMap<>();
    //                    for (String cacheName : configMap.keySet()) {
    //                        configurationMap.
    //                                put(cacheName, RedisCacheConfiguration
    //                                        .defaultCacheConfig()
    //                                        .computePrefixWith(name -> appName + ":" + name + ":")
    //                                        .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
    //                                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericFastJsonRedisSerializer()))
    //                                        .entryTtl(Duration.ofSeconds(configMap.get(cacheName))));
    //                    }
    //                    builder.withInitialCacheConfigurations(configurationMap);
    //                    log.info("Redis缓存配置为:{}",configMap.toString());
    //                }
    //            } catch (IllegalAccessException illegalEx) {
    //                log.error("SpringCache RedisCacheManagerBuilderCustomizer配置失败,启动终止。请检查RedisCacheManagerBuilder类中ReflectUtil.getCacheTtlConfigMap()部分", illegalEx);
    //                System.exit(500);
    //            }
    //        };
    //    }
    
        static class ReflectUtil {
            public static final String CACHE_NAME_PREFIX = "CACHE_NAME_";
            public static final String CACHE_TTL_PREFIX = "CACHE_TTL_";
    
            static <T> Map<String, Integer> getCacheTtlConfigMap(Class<T> clazz) throws IllegalAccessException {
                Map<String, Integer> cacheMapWithKeyTtl = new HashMap<>();
                Field[] fields = clazz.getFields();
                Map<String, String> cacheNames = new HashMap<>(fields.length);
                // 配置cacheName
                for (Field field : fields) {
                    if (field.getName().contains(CACHE_NAME_PREFIX)) {
                        if (field.getType().equals(String.class)) {
                            String lookingForTtlName = field.getName().replace(CACHE_NAME_PREFIX, CACHE_TTL_PREFIX);
                            String value = (String) field.get(clazz);
                            cacheNames.put(lookingForTtlName, value);
                        } else {
                            throw new IllegalAccessException("In constants configuration, the type of prefix of cache must be String. Illegal in " + clazz.getName() + "." + field.getName() + ".");
                        }
                    }
                }
                // 配置过期时间
                for (Field field : fields) {
                    if (field.getName().contains(CACHE_TTL_PREFIX)) {
                        if (field.getType().equals(int.class) || field.getType().equals(Integer.class)) {
                            if (cacheNames.containsKey(field.getName())) {
                                cacheMapWithKeyTtl.put(cacheNames.get(field.getName()), field.getInt(clazz));
                            }
                        } else {
                            throw new IllegalAccessException("In constants configuration, the type of prefix of ttl must be int or Integer. Illegal in " + clazz.getName() + "." + field.getName() + ".");
                        }
                    }
                }
                // 配置默认过期时间
                for (String cacheNameKey : cacheNames.keySet()) {
                    String cacheName = cacheNames.get(cacheNameKey);
                    if (!cacheMapWithKeyTtl.containsKey(cacheNames.get(cacheNameKey))) {
                        log.warn("===========================Spring Cache Config 配置信息错误=========================");
                        log.warn("Spring Cache Config 配置信息错误:{}文件中的缓存{}没有查询到对应失效时间的配置信息,将按默认值180秒执行。", clazz.getName(), cacheName);
                        log.warn("=============================== Zora Cache Config ================================");
                        cacheMapWithKeyTtl.put(cacheName, DEFAULT_EXPIRE_SECOND);
                    }
                }
                return cacheMapWithKeyTtl;
            }
        }
    }
    
  • 相关阅读:
    css
    团队介绍
    day4
    线段树懒标记
    P2014选课
    P2015
    扩展欧几里得(exgcd)求解不定方程/求逆元
    transform和tolower
    快读
    bzoj2118
  • 原文地址:https://www.cnblogs.com/ZoraZora59/p/12455539.html
Copyright © 2011-2022 走看看