簡單說說註解到底用在哪了?

本文只簡單分析註解的使用,供註解初學者嘗試使用,使用過程當中還須要本身增強原理追溯;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); } }
相關文章
相關標籤/搜索