JAVASE 的API并沒(méi)有提供獲取枚舉值注解信息的方法,只能獲取到enum類(lèi)上的注解冰蘑,但是有一種場(chǎng)景:通過(guò)注解為枚舉值增加額外的功能和泌。
enum作為數(shù)據(jù)字典,當(dāng)為enum的各個(gè)枚舉值增加一個(gè)新的屬性值時(shí)祠肥,有兩種方式:
- 增加一個(gè)屬性值武氓,通過(guò)多種參數(shù)的構(gòu)造方法,來(lái)實(shí)現(xiàn)仇箱;
- 增加一個(gè)注解县恕,并且放置在枚舉值上;
本文來(lái)實(shí)現(xiàn)第二種方式剂桥,遇見(jiàn)的難題:JAVASE 的API并沒(méi)有提供獲取枚舉值注解信息的方法忠烛,只能獲取到enum類(lèi)上的注解。
解決辦法:通過(guò)獲取枚舉值Field對(duì)象权逗,來(lái)實(shí)現(xiàn):
實(shí)現(xiàn)
兩個(gè)注解:需要去增強(qiáng)枚舉值的功能
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Log {
//是否開(kāi)啟
boolean open() default false;
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface Cost {
double min();
double max();
}
解析方法:
/**
* 隨意一個(gè)枚舉
*/
@Getter
public enum StudyEnum {
@Log(open = true)
@Cost(min = 10.0, max = 99.0)
JAVA("java", "java基礎(chǔ)"),
@Cost(min = 20.0, max = 79.0)
PHP("php", "php基礎(chǔ)");
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;
}
//對(duì)象初始化時(shí)美尸,執(zhí)行下面的方法,將注解上的枚舉值解析到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);
//獲取價(jià)格注解
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);
}
}
//解析花費(fèi)注解
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;
}
}
測(cè)試方法:
public class TestStudy {
//完成對(duì)象的解析
public static void main(String[] args) {
//info對(duì)象
StudyEnum.StudyEnumInfo info = StudyEnum.JAVA.resolve();
System.out.println(info.getCostAnno().max());
System.out.println(info.getLogAnno().open());
}
}