美文网首页jdk开发
[JAVA基础篇25]—反射读取枚举值上的注解信息

[JAVA基础篇25]—反射读取枚举值上的注解信息

作者: 小胖学编程 | 来源:发表于2021-10-25 16:17 被阅读0次

    JAVASE 的API并没有提供获取枚举值注解信息的方法,只能获取到enum类上的注解,但是有一种场景:通过注解为枚举值增加额外的功能。

    enum作为数据字典,当为enum的各个枚举值增加一个新的属性值时,有两种方式:

    1. 增加一个属性值,通过多种参数的构造方法,来实现;
    2. 增加一个注解,并且放置在枚举值上;

    本文来实现第二种方式,遇见的难题:JAVASE 的API并没有提供获取枚举值注解信息的方法,只能获取到enum类上的注解。

    解决办法:通过获取枚举值Field对象,来实现:

    实现

    两个注解:需要去增强枚举值的功能

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD, ElementType.TYPE})
    public @interface Log {
    
        //是否开启
        boolean open() default false;
    
    }
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD, ElementType.TYPE})
    public @interface Cost {
    
        double min();
    
        double max();
    }
    

    解析方法:

    /**
     * 随意一个枚举
     */
    @Getter
    public enum StudyEnum {
    
        @Log(open = true)
        @Cost(min = 10.0, max = 99.0)
        JAVA("java", "java基础"),
    
        @Cost(min = 20.0, max = 79.0)
        PHP("php", "php基础");
    
        private String actualName;
    
        private String desc;
        
        private static final Map<String, Cost> costCache = new HashedMap<>();
        private static final Map<String, Log> logCache = new HashedMap<>();
    
        private static final Map<String, StudyEnum> cache = new HashedMap<>();
    
        StudyEnum(String actualName, String desc) {
            this.actualName = actualName;
            this.desc = desc;
        }
        
        //对象初始化时,执行下面的方法,将注解上的枚举值解析到cache中
        static {
            //将枚举属性值的name和Field映射为Map
            Map<String, Field> fieldCache = Arrays.stream(StudyEnum.class.getDeclaredFields()).
                    filter(Field::isEnumConstant).
                    collect(Collectors.toMap(Field::getName, Function.identity()));
            //遍历所有的枚举值
            for (StudyEnum studyEnum : StudyEnum.class.getEnumConstants()) {
                String keyName = studyEnum.name();
                //原始的cache
                cache.put(keyName, studyEnum);
                Field field = fieldCache.get(keyName);
                //不包含原始,则停止解析
                if (!field.isAnnotationPresent(Log.class) || !field.isAnnotationPresent(Cost.class)) {
                    continue;
                }
                //获取日志注解
                parsingLogAnno(keyName, field);
                //获取价格注解
                parsingCostAnno(keyName, field);
            }
        }
    
    
        /**
         * 获取注解的属性
         */
        public static StudyEnumInfo resolve(String name) {
            StudyEnum studyEnum = cache.get(name);
            if (studyEnum == null) {
                return null;
            }
            Log log = logCache.get(name);
            Cost cost = costCache.get(name);
            StudyEnumInfo studyEnumInfo = new StudyEnumInfo();
            studyEnumInfo.setName(studyEnumInfo.name);
            studyEnumInfo.setDesc(studyEnum.desc);
            studyEnumInfo.setLogAnno(log);
            studyEnumInfo.setCostAnno(cost);
            return studyEnumInfo;
        }
    
        /**
         * 获取注解的属性
         */
        public StudyEnumInfo resolve() {
            return resolve(this.name());
        }
    
    
        //解析日志注解
        private static void parsingLogAnno(String keyName, Field field) {
            Log logAnno = field.getDeclaredAnnotation(Log.class);
            if (logAnno != null) {
                logCache.put(keyName, logAnno);
            }
        }
    
        //解析花费注解
        private static void parsingCostAnno(String keyName, Field field) {
            Cost costAnno = field.getDeclaredAnnotation(Cost.class);
            if (costAnno != null) {
                costCache.put(keyName, costAnno);
            }
        }
    
    
        @Data
        public static class StudyEnumInfo {
            private String name;
    
            private String desc;
    
            private Log logAnno;
    
            private Cost costAnno;
        }
    }
    

    测试方法:

    public class TestStudy {
    
        //完成对象的解析
        public static void main(String[] args) {
            //info对象
            StudyEnum.StudyEnumInfo info = StudyEnum.JAVA.resolve();
            System.out.println(info.getCostAnno().max());
            System.out.println(info.getLogAnno().open());
        }
    }
    

    相关文章

      网友评论

        本文标题:[JAVA基础篇25]—反射读取枚举值上的注解信息

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