• 为什么这么做? 为了springboot 注解属性转换字典方便一点(使用缓存的方式在Springboot 启动时获取字典数据)

  • 在启动时会扫描com.vehicle.manager.core.enumerate包下的所有枚举(包括类中的内部枚举),并取出对应属性以json的方式存入redis

  • 目录结构如下:

image.png

  • RedisUtil可以在RedisUtil获取
  • Springboot 项目启动时的处理都可以参考这个方式
package com.vehicle.manager.core.enumerate;

import com.alibaba.fastjson.JSON;
import com.vehicle.manager.core.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author zr 2024/3/15
 */
@Component
@Order(1) // 确保在其他 Bean 初始化之前执行
@Slf4j
public class EnumScanner implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private ApplicationContext applicationContext;

    private StringRedisTemplate redisTemplate;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (event.getApplicationContext().equals(applicationContext)) {
            this.redisTemplate = applicationContext.getBean(StringRedisTemplate.class);
            scanEnums();
        }
    }

    public void scanEnums() {
//        String dicDataStr = RedisUtil.StringOps.get("dicData");
//        if (ObjectUtils.isNotEmpty(dicDataStr)){
//            return;
//        }
        String packageName = "com.vehicle.manager.core.enumerate"; // 替换成你要扫描的包路径
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AssignableTypeFilter(Enum.class));

        Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(packageName);
        HashMap<String, Map<String, String>> dicData = new HashMap<>();
        for (BeanDefinition candidateComponent : candidateComponents) {
            String className = candidateComponent.getBeanClassName();
            // 这里可以对枚举类进行处理,比如输出类名或者其他操作
//            log.info("Found enum class: " + className);

            Class<?> enumClass = null;
            try {
                enumClass = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }

            if (enumClass.isEnum()) {
                Map<String,String> dic = new LinkedHashMap();
                Object[] enumConstants = enumClass.getEnumConstants();
                for (Object enumConstant : enumConstants) {
//                    log.info("enumConstant",enumConstant);
                    dic.put(enumConstant.toString(),getDesc(enumConstant));
                }
                String simpleName = enumClass.getSimpleName();
                String key = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1);

                dicData.put(key,dic);

            }
//            dicData.put(key, JSON.toJSONString());

        }
        RedisUtil.StringOps.set("dicData", JSON.toJSONString(dicData));

    }

    private static  String  getDesc(Object enumConstant) {
        try {
            Field descField = enumConstant.getClass().getDeclaredField("desc");
            descField.setAccessible(true);
            String methodName = "get" + descField.getName().substring(0, 1).toUpperCase() + descField.getName().substring(1);
            Method getDescMethod = enumConstant.getClass().getMethod(methodName);
            return (String) getDescMethod.invoke(enumConstant);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

存入redis中的数据结构如下:

  • json中的key为枚举的名称首字母小写
  • 当然用redis的hash结构存储更好,当时开发时没有考虑到,有需要的可以自己改造

image.png

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部