Memo Class
1. 什么是Memo Class
Memo class其实就是备注类信息,很多人会问为什么要备注类信息,其实这个功能词汇并不常见,但是我就是在开发过程中遇到了这个功能实现。场景是这样的,我要实现一个通知模块,负责根据流程配置来处理消息,然后将消息发送出去。其中有一个步骤就是根据消息模板渲染消息,在这个渲染过程中,如果模板是页面可管理的,那么页面在配置模板的时候,要知道消息数据中的键值对应该模板中热数据的键值是什么,显然模板是页面可管理的,那么就是要模板的键值依赖于调用者传入的接口模型数据,在这种条件下要管理模板就需要知道调用者的数据模型键值说明,这个时候如果能把这个数据模型备注出来让模板管理者查看,那么模板管理者就能很好的管理自己的模板,根据需要调整要显示的数据。
上面的场景可能过于拗口,简单点说就是在一些大的项目中,我们需要将我们模型数据展示到页面上方便管理和让其他使用的人查看。
2. Memo Class的案例
如下需要将下面简单的数据模型 MsgObject的属性信息构建展示出去,让使用者在页面可以查看属性信息,我们可以通过构建类的注解来备注该数据模型,提取其中的注解信息展示出去,类构建如下:
自定义注解类,有用注解备注类属性和class的信息,相当于给模型数据配置了一个xml信息文档说明。
存储注解信息的对象模型类
注解处理备注类实现如下,通过类结构反射遍历数据模型属性,逐层递归处理我们想要展示的结果,实现如下:
测试类实现
运行结果:
从结果可以看出,已将备注类的信息输出
1. 什么是Memo Class
Memo class其实就是备注类信息,很多人会问为什么要备注类信息,其实这个功能词汇并不常见,但是我就是在开发过程中遇到了这个功能实现。场景是这样的,我要实现一个通知模块,负责根据流程配置来处理消息,然后将消息发送出去。其中有一个步骤就是根据消息模板渲染消息,在这个渲染过程中,如果模板是页面可管理的,那么页面在配置模板的时候,要知道消息数据中的键值对应该模板中热数据的键值是什么,显然模板是页面可管理的,那么就是要模板的键值依赖于调用者传入的接口模型数据,在这种条件下要管理模板就需要知道调用者的数据模型键值说明,这个时候如果能把这个数据模型备注出来让模板管理者查看,那么模板管理者就能很好的管理自己的模板,根据需要调整要显示的数据。
上面的场景可能过于拗口,简单点说就是在一些大的项目中,我们需要将我们模型数据展示到页面上方便管理和让其他使用的人查看。
2. Memo Class的案例
如下需要将下面简单的数据模型 MsgObject的属性信息构建展示出去,让使用者在页面可以查看属性信息,我们可以通过构建类的注解来备注该数据模型,提取其中的注解信息展示出去,类构建如下:
package com.annotation.memo;
/**
* @author xmong
*/
public class MsgObject {
@MsgType(memo="消息名称")
String name;
@MsgType(memo="测试消息")
MsgTest msgTest;
}
class MsgTest{
@MsgType(memo="名称")
String name;
}
自定义注解类,有用注解备注类属性和class的信息,相当于给模型数据配置了一个xml信息文档说明。
package com.annotation.memo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 注解类,备注类信息
* @author xmong
*/
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MsgType {
/**
* key值注解,默认值为空字符串
* @return
*/
public String key() default AnnotationConfig.DEFAULT_KEY;
/**
* 备注注解,默认值为空字符串
* @return
*/
public String memo() default AnnotationConfig.DEFAULT_MEMO;
}
package com.annotation.memo;
/**
* @author xmong
*/
public interface AnnotationConfig {
//key 默认值
public String DEFAULT_KEY = "";
//备注默认值
public String DEFAULT_MEMO = "";
}
存储注解信息的对象模型类
package com.annotation.memo;
/**
* 备注信息封装类
* @author xmong
*/
public class MsgMemo {
/**
* key值,对于类属性名或者是备注key
*/
private String key;
/**
* 备注信息
*/
private String memo;
/**
* 值类型
*/
private String type;
/**
* 默认属性分隔符
*/
public static String DEFAULT_SPLIT_SIGN = ".";
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getMemo() {
return memo;
}
public void setMemo(String memo) {
this.memo = memo;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public void appendKey(String key){
this.key = null == this.key ? key : this.key+DEFAULT_SPLIT_SIGN+key;
}
public void appendMemo(String memo){
this.memo = null == this.memo ? memo : this.memo+DEFAULT_SPLIT_SIGN+memo;
}
@Override
public String toString() {
return "{key:"+getKey()
+", memo:"+getMemo()
+", type:"+getType()+"}";
}
}
注解处理备注类实现如下,通过类结构反射遍历数据模型属性,逐层递归处理我们想要展示的结果,实现如下:
package com.annotation.memo;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 备注构建类
* @author xmong
*/
public class AnnotationMsgHandler {
/**
* map对象名为key,value为对象属性注解信息类列表
*/
public static Map<String, List<MsgMemo>> memoMap = new HashMap<String, List<MsgMemo>>();
/**
* 对象属性注解信息列表类
*/
public static List<MsgMemo> memoList = new ArrayList<MsgMemo>();
/**
* 静态代码执行
*/
static{
doBuilderMsgList(new MsgObject());
doBuilderMsgMap(new MsgObject());
}
public static void doBuilderMsgMap(Object obj){
builderMsgMap(obj.getClass(), memoMap);
}
public static void doBuilderMsgList(Object obj){
builderMsgList(obj.getClass(), memoList, null, null);
}
public static void builderMsgMap(Class<?> c, Map<String, List<MsgMemo>> map){
//获取类的属性
Field[] fields = c.getDeclaredFields();
List<MsgMemo> list = new ArrayList<MsgMemo>();
//根据类名保存属性列表
map.put(c.getSimpleName(), list);
//遍历属性
for (Field field : fields) {
//判断属性是否被注解,没有被注解则进入下一次循环
if(!field.isAnnotationPresent(MsgType.class)) continue;
//获取注解
MsgType msgType = field.getAnnotation(MsgType.class);
//获取注解key值,如果key存在,则属性为key值,如果属性为默认值则属性为类属性名
String keyMsg = AnnotationConfig.DEFAULT_KEY.equals(msgType.key())
? field.getName() : msgType.key();
//构建属性信息
MsgMemo msgMemo = new MsgMemo();
msgMemo.appendKey(keyMsg);
msgMemo.appendMemo(msgType.memo());
msgMemo.setType(field.getGenericType().toString());
list.add(msgMemo); //属性注解加入列表
/**
* 判断是否为java常用类,如果不为java基本变量和java常用类,
* 则继续递归处理该属性类循环,反之既然
*/
if(field.getType().toString().toLowerCase().startsWith("class")
&&!field.getType().getName().startsWith("java.lang")
&&!field.getType().getName().startsWith("java.util")){
//递归调用
builderMsgMap(field.getType(), map);
}
}
}
public static void builderMsgList(Class<?> c, List<MsgMemo> list, String key, String memo){
//获取类属性
Field[] fields = c.getDeclaredFields();
//遍历类属性
for (Field field : fields) {
if(!field.isAnnotationPresent(MsgType.class)) continue;
MsgType msgType = field.getAnnotation(MsgType.class);
String keyMsg = AnnotationConfig.DEFAULT_KEY.equals(msgType.key())
? field.getName() : msgType.key();
MsgMemo msgMemo = new MsgMemo();
msgMemo.setKey(key);
msgMemo.setMemo(memo);
msgMemo.appendKey(keyMsg);
msgMemo.appendMemo(msgType.memo());
/**
* 如果属性为基本变量和常用类,则保存到列表中
* 反之则递归处理该属性类
*/
if(!field.getType().toString().toLowerCase().startsWith("class")
||field.getType().getName().startsWith("java.lang")
||field.getType().getName().startsWith("java.util")){
msgMemo.setType(field.getGenericType().toString());
list.add(msgMemo);
}else{
//递归调用
builderMsgList(field.getType(), list, msgMemo.getKey(), msgMemo.getMemo());
}
}
}
public static Map<String, List<MsgMemo>> getMemoMap() {
return memoMap;
}
public static void setMemoMap(Map<String, List<MsgMemo>> memoMap) {
AnnotationMsgHandler.memoMap = memoMap;
}
public static List<MsgMemo> getMemoList() {
return memoList;
}
public static void setMemoList(List<MsgMemo> memoList) {
AnnotationMsgHandler.memoList = memoList;
}
}
测试类实现
package com.annotation.memo;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* @author xmong
*/
public class Test {
public static void main(String[] args) {
/**
* 遍历列表输出注解信息
*/
List<MsgMemo> list = AnnotationMsgHandler.getMemoList();
for (MsgMemo msgMemo : list) {
System.out.println(msgMemo);
}
/**
* 遍历map输出类注解信息
*/
Map<String, List<MsgMemo>> map = AnnotationMsgHandler.getMemoMap();
for (Entry<String, List<MsgMemo>> entry : map.entrySet()) {
System.out.println(entry);
}
}
}
运行结果:
{key:name, memo:消息名称, type:class java.lang.String}
{key:msgTest.name, memo:测试消息.名称, type:class java.lang.String}
MsgObject=[{key:name, memo:消息名称, type:class java.lang.String}, {key:msgTest, memo:测试消息, type:class com.annotation.memo.MsgTest}]
MsgTest=[{key:name, memo:名称, type:class java.lang.String}]
从结果可以看出,已将备注类的信息输出