本文只簡單分析註解的使用,供註解初學者嘗試使用,使用過程當中還須要本身增強原理追溯;java
包含(註解是什麼,如何自定義註解,註解做用在那裏,如何在開發中使用註解)api
一、註解是什麼?測試
官方定義:spa
註解(Annotation),也叫元數據。一種代碼級別的說明。
what ???? 啥是元數據??代理
元數據:描述數據的數據。(舉例:我形容某我的,哪身高,體重,膚色,頭髮等 就是元數據了)對象
可是,註解是描述什麼的呢?(類, 方法, 屬性..)blog
常規理解:註解就是對指定對象的額外信息指定和約束,但這個指定和約束必須要有監督者,才真正發揮做用。 開發
好比:get
@Target({ElementType.FIELD, ElementType.METHOD}) // 做用對象(FIELD:屬性,METHOD:方法 固然還有其餘枚舉,) @Retention(RetentionPolicy.RUNTIME) //(運行時生效) public @interface FieldCanNotNull { }
上面就是一個簡單入門的註解,在運行的時候,是有效的,可被獲取及解析的。
//測試類 public class Person{ @FieldCanNotNull //這個註解就是鹹魚 private String merchangNO; }
可是,這個在沒有代碼解釋的時候,毫無心義。
怎麼才能讓它變得有意義,有價值?
那就是經過某種方式 ,能夠在運行的時候獲取到這個對象的 merchangNO 屬性信息,而且獲取這個屬性的元數據。而 @FieldCanNotNull 就是元數據。
想要獲取的話,那就須要經過反射的方式,或者當前類的基礎信息,並獲取當前屬性的註解信息。
/** * 屬性非空校驗 * @param object * @return */ public static boolean isNull4fields(Object object){ if (isNull(object)){ throw NetInException.PARAM_REQUIRED_ERROR.newInstance("object can not be null"); } List<Field> fields = getAllFields(object.getClass(), new ArrayList<>()); //獲取全部屬性 if (CollectionUtils.isEmpty(fields)){ return false; } Iterator<Field> iterator = fields.iterator(); //獲取迭代器 Object fieldVal; while ( iterator.hasNext()) { Field field = iterator.next(); if ( field.isAnnotationPresent(FieldCanNotNull.class)){ //判斷當前屬性是否有 FieldCanNotNull 註解 fieldVal = invokeGetMethod(field.getName(), "", object); //調用當前屬性的get 方法獲取屬性值 if(isNull(fieldVal)){ //若是當前屬性址是空 String errMsg = field.getName() + " can not be null"; //組裝信息 拋出異常 throw NetInException.PARAM_REQUIRED_ERROR.newInstance(errMsg, null); } }else{ continue; } } return false; }
真正有意義就是這一段利用反射,獲取屬性值,比較註解約束內容。而這個方法的邏輯就是赤裸裸的監督者! 監督被約束的對象是否按照約定進行。it
因此: 註解是魚 , 反射解析是水, 二者相輔相成。
好的! 那麼我們進入一個全流程(自定義註解)
一、定義註解(也就是創建法律約束)
二、在將要被約束的對象/方法/屬性 上添加註解(法律針對對象)
三、特定的反射功能,獲取註解,解析註解並校驗 (法律解讀,監督者檢查是否違背法律)
四、在特定的地方調用反射功能 也就是調用監督者。
開發過程什麼狀況下使用註解?
一、有校驗需求時
二、有約束需求時
三、有隔離了本來業務的非業務功能時 ...
等等,這個感受有點像AOP的思想啊,沒錯,咱們在使用的過程通常還真的是把這個監督者使用AOP思想來實現。這樣就從核心業務上把註解給解析判斷嘍!
那怎麼樣呢?還有啥?
既然是AOP那麼代理是必然要有的。
因此最終經常使用的就是 , 在代理類中 使用反射 前置處理 解析註解 最後調用目標方法;
例以下面:使用Spring實現AOP 在調用方法以前,進行前置註解解析和處理
前置處理(AOP)
@Aspect public class VerifyAop { /** * 校驗參數 * @param joinPoint * @throws Throwable */ public void verifyMethod(JoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); for (Object arg:args){ VerifyUtil.isNull4fields(arg); } } /** * 環繞處理 * @param point * @return * @throws Throwable */ public Object exeMethod(ProceedingJoinPoint point) throws Throwable { return point.proceed(); } }
校驗方法(監督者)
public class VerifyUtil { private VerifyUtil(){}; /** * 校驗參數爲否爲空 * @param param * @param paramDesc 參數名 */ public static void validateNotEmptyParam(Object param, String paramDesc){ if (param == null){ throw NetInException.PARAM_REQUIRED_ERROR.newInstance(paramDesc + "爲必填項"); } if ((param instanceof Map && MapUtils.isEmpty((Map)param)) || (param.getClass().isArray() && ArrayUtils.getLength(param) ==0) || (param instanceof CollectionUtils && CollectionUtils.isEmpty((Collection)param)) || (param instanceof String && StringUtils.isEmpty(((String)param).trim()))){ throw NetInException.PARAM_VALIDATE_ERROR.newInstance(paramDesc + "不能爲空"); } } /** * 判斷對象是否爲空 * @param object * @return */ public static boolean isNull(Object object){ if (object==null){ return true; }else if (StringUtils.isEmpty(object.toString())){ return true; } return false; }
/** * 屬性非空校驗 * @param object * @return */ public static boolean isNull4fields(Object object){ if (isNull(object)){ throw NetInException.PARAM_REQUIRED_ERROR.newInstance("object can not be null"); } List<Field> fields = getAllFields(object.getClass(), new ArrayList<>()); //獲取全部屬性 if (CollectionUtils.isEmpty(fields)){ return false; } Iterator<Field> iterator = fields.iterator(); //獲取迭代器 Object fieldVal; while ( iterator.hasNext()) { Field field = iterator.next(); if ( field.isAnnotationPresent(FieldCanNotNull.class)){ //判斷當前屬性是否有 FieldCanNotNull 註解 fieldVal = invokeGetMethod(field.getName(), "", object); //調用當前屬性的get 方法獲取屬性值 if(isNull(fieldVal)){ //若是當前屬性址是空 String errMsg = field.getName() + " can not be null"; //組裝信息 拋出異常 throw NetInException.PARAM_REQUIRED_ERROR.newInstance(errMsg, null); } }else{ continue; } } return false; }
/** *獲取當前類及當前類的多層父類屬性集合 * @param clazz * @param fields * @return */ public static List<Field> getAllFields(Class clazz,List<Field> fields ){ Field[] declaredFields = clazz.getDeclaredFields(); Class superclass = clazz.getSuperclass(); if (superclass == null || "Object".equals(superclass.getSimpleName())){ fields.addAll(Lists.newArrayList(declaredFields)); return fields; }else { List<Field> fieldsList = Arrays.asList(declaredFields); fields.addAll(fieldsList); getAllFields(superclass, fields); } return fields; } /** * 調用指定對象的getXX 方法(用於獲取某個對象的某個屬性的值) * @param fieldName * @param suffix * @param object * @return */ private static Object invokeGetMethod(String fieldName, String suffix, Object object ) { Method mget = ReflectionUtils.findMethod(object.getClass(), "get" + StringUtils.capitalize(fieldName) + StringUtils.trimToEmpty(suffix)); return ReflectionUtils.invokeMethod(mget, object); } }