为什么这么做? 为了springboot 注解属性转换字典方便一点(使用缓存的方式在Springboot 启动时获取字典数据)
在启动时会扫描com.vehicle.manager.core.enumerate包下的所有枚举(包括类中的内部枚举),并取出对应属性以json的方式存入redis
目录结构如下:
- 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> {@Autowiredprivate ApplicationContext applicationContext;private StringRedisTemplate redisTemplate;@Overridepublic 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结构存储更好,当时开发时没有考虑到,有需要的可以自己改造