利用反射注册SpringCache的RedisCacheManager缓存信息

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

配置类如下:

public class Constants {
    public static final String CACHE_NAME_MAIN = "main_cache_name";
    public static final int CACHE_TTL_MAIN = 50;
    public static final String CACHE_NAME_DEMO = "demo_cache_name";
    public static final int CACHE_TTL_DEMO = 100;
}

然后通过反射,将各属性转到map中,通过遍历map来进行全部注册。

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
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;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 缓存配置工具
 *
 * @author Zorazora
 * @since 2020/3/9
 */
@Configuration
@Slf4j
public class RedisCacheManagerBuilder {
    @Value("${spring.application.name}")
    private String appName;

    @Bean
    public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
        return builder -> {
            try {
                // 这里的参数填充对应的静态属性类
                Map<String, Integer> configMap = ReflectUtil.getCacheTtlConfigMap(Constants.class);
                if (!configMap.isEmpty()) {
                    for (String cacheName : configMap.keySet()) {
                        builder.withCacheConfiguration(cacheName, RedisCacheConfiguration
                                .defaultCacheConfig()
                                .computePrefixWith(name -> appName + ":" + name + ":")
                                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new FastJsonRedisSerializer<>(Object.class)))
                                .entryTtl(Duration.ofSeconds(configMap.get(cacheName))));
                    }
                }
            } 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);
            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() + ".");
                    }
                }
            }
            return cacheMapWithKeyTtl;
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/ZoraZora59/p/12455539.html