JAVASE 的API并没有提供获取枚举值注解信息的方法,只能获取到enum类上的注解,但是有一种场景:通过注解为枚举值增加额外的功能。
enum作为数据字典,当为enum的各个枚举值增加一个新的属性值时,有两种方式:
- 增加一个属性值,通过多种参数的构造方法,来实现;
- 增加一个注解,并且放置在枚举值上;
本文来实现第二种方式,遇见的难题: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();
}
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;
public String getActualName() {
return actualName;
}
public void setActualName(String actualName) {
this.actualName = actualName;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
private static final Map<String, Cost> costCache = new HashMap<>();
private static final Map<String, Log> logCache = new HashMap<>();
private static final Map<String, StudyEnum> cache = new HashMap<>();
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 Test {
//完成对象的解析
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());
}
}
运行结果