java注解

介紹

java 1.5引入了注解(annotation),注解類似注釋,不同的是注解除了提供代碼說明,
還能實現(xiàn)程序的邏輯功能,在很多java框架中都得到了廣發(fā)的應(yīng)用贵涵。

元注解

元注解的作用就是負(fù)責(zé)注解其他注解。Java5.0定義了4個標(biāo)準(zhǔn)的meta-annotation類型恰画,它們被用來提供對其它 annotation類型作說明宾茂。

  • @Target 修飾了注解使用范圍 可以是類(TYPE),方法(METHOD),字段(FIELD),構(gòu)造函數(shù)(CONSTRUCTOR),參數(shù)(PARAMETER)拴还,局部變量(LOCAL_VARIABLE)刻炒,包(PACKAGE)
  • @Retention 修飾了注解存在的時間 SOURCE 只在源碼中出現(xiàn),CLASS 只在Class文件可以看見 RUNTIME 運行時也可以看見
  • @Documented 用來修飾注解是否出現(xiàn)在API中
  • @Inherited 是否會被子類繼承 注解正常只出現(xiàn)在父類 子類不繼承 加上這個標(biāo)記 子類也能獲得注解

示例代碼

給類付上額外的信息

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ClassAnno {
    String value() default "類注解";
}

@ClassAnno("Test類")
public class Test {

}

public class Main {

    public static void main(String ...args){
        ClassAnno classAnno=Test.class.getAnnotation(ClassAnno.class);
        if(classAnno!=null){
            System.out.println(classAnno.value());
        }
    }
}

測試方法

  • 去掉Test類上的注解 查看結(jié)果
  • 去掉Test類上注解的值 查看結(jié)果

注解應(yīng)用 驗證類

一個驗證接口

/**
 * 驗證接口
 * @param <T> 值類型
 * @param <A> 注解類型
 */
public interface Validator<T,A> {

    /**
     * 驗證方法
     * @param value 值
     * @param anno  注解
     * @return  錯誤信息 如果是null表示無錯誤
     */
    String validate(T value,A anno);
}

實現(xiàn)一個注解和驗證接口實現(xiàn)類的綁定

/**
 * 綁定注解和驗證類
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidatorBind {
    /**
     * 驗證類
     * @return
     */
    Class validator();
}

實現(xiàn)一個接受驗證結(jié)果的類

/**
 * 驗證結(jié)果
 */
public class ValidatorResult {
    /**
     * 錯誤信息
     */
    private String message;
    /**
     * 字段名稱
     */
    private String fieldName;
    /**
     * 字段路徑
     */
    private String fieldPath;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getFieldName() {
        return fieldName;
    }

    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    public String getFieldPath() {
        return fieldPath;
    }

    public void setFieldPath(String fieldPath) {
        this.fieldPath = fieldPath;
    }
}

實現(xiàn)一個驗證工具

public class ValidatorUtil {

    /**
     * 獲取所有字段
     * @param clz
     */
    public static List<Field> getAllField(Class clz){
        Field[] declaredFields = clz.getDeclaredFields();
        Field[] fields=clz.getFields();
        List<Field> fieldList=new ArrayList<>(fields.length+declaredFields.length);
        for(int i=0;i<declaredFields.length;i++){
            declaredFields[i].setAccessible(true);
            fieldList.add(declaredFields[i]);
        }
        for(int i=0;i<fields.length;i++){
            fieldList.add(fields[i]);
        }
        return fieldList;
    }

    /**
     * 驗證對象的某個字段是否符合規(guī)則
     * @param field 字段
     * @param object 對象
     * @param results 錯誤結(jié)果存儲
     * @return
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    private static boolean validatorField(Field field, Object object,List<ValidatorResult> results) throws IllegalAccessException, InstantiationException {
        Annotation[] annos = field.getAnnotations();
        for(Annotation annotation:annos){
            ValidatorBind validatorBind=annotation.annotationType().getAnnotation(ValidatorBind.class);
            if(validatorBind!=null){
               Validator validator= (Validator) validatorBind.validator().newInstance();
               String msg=validator.validate(field.get(object),annotation);
               if(msg!=null){
                   ValidatorResult validatorResult=new ValidatorResult();
                   validatorResult.setFieldName(field.getName());
                   validatorResult.setMessage(msg);
                   results.add(validatorResult);
                   return false;
               };
            }
        }
        return true;
    }

    /**
     * 驗證對象
     * @param object
     * @return 錯誤結(jié)果合集
     */
    public static List<ValidatorResult> validator(Object object){
        //返回結(jié)果
        List<ValidatorResult> results=new ArrayList<>();
        Class clz=object.getClass();
        List<Field> fields=getAllField(clz);
        for(Field field:fields){
            try {
                validatorField(field,object,results);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
        return results;
    }
}

上面一個驗證框架就完成了
下面是增加驗證功能
增加一個NotNull驗證

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@ValidatorBind(validator = NotNullValidator.class)
@interface NotNull {
    String msg() default "不能為空";
}

實現(xiàn)類

/**
 * 驗證Object不是NULL
 */
public class NotNullValidator implements Validator<Object,NotNull> {

    /**
     *  驗證不能為NULL
     * @param value 值 Object類型
     * @param anno  注解 NotNull注解
     * @return
     */
    @Override
    public String validate(Object value, NotNull anno) {
        if(value==null){
            return anno.msg();
        }
        return null;
    }
}

增加正則驗證

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@ValidatorBind(validator = PatternValidator.class)
public @interface Pattern {
    String regexp() default "";
    String msg() default "不符合正則規(guī)則";
}

實現(xiàn)正則驗證規(guī)則

public class PatternValidator implements Validator<String,Pattern> {
    @Override
    public String validate(String value, Pattern anno) {
        String regexp=anno.regexp();
        if(!RegExp.test(regexp,value)){
            return anno.msg();
        }
        return null;
    }
}

測試類

class A {
    @NotNull
    @Pattern(regexp = "^\\d+$",msg = "必須是純數(shù)字")
    String name;
}

public class Main {

    public static void main(String ...args){
        A a=new A();
        a.name="asd";
        List<ValidatorResult> list = ValidatorUtil.validator(a);
        if(list.isEmpty()){
            System.out.println("通過驗證");
        }else{
            for(ValidatorResult result:list) {
                System.out.println(result.getFieldName()+' '+result.getMessage());
            }
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末自沧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子树瞭,更是在濱河造成了極大的恐慌拇厢,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晒喷,死亡現(xiàn)場離奇詭異孝偎,居然都是意外死亡,警方通過查閱死者的電腦和手機凉敲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門衣盾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人爷抓,你說我怎么就攤上這事势决。” “怎么了蓝撇?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵果复,是天一觀的道長。 經(jīng)常有香客問我渤昌,道長虽抄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任独柑,我火速辦了婚禮迈窟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘忌栅。我一直安慰自己车酣,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著骇径,像睡著了一般躯肌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上破衔,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天清女,我揣著相機與錄音,去河邊找鬼晰筛。 笑死嫡丙,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的读第。 我是一名探鬼主播曙博,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼怜瞒!你這毒婦竟也來了父泳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤吴汪,失蹤者是張志新(化名)和其女友劉穎惠窄,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體漾橙,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡杆融,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了霜运。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脾歇。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖淘捡,靈堂內(nèi)的尸體忽然破棺而出藕各,到底是詐尸還是另有隱情,我是刑警寧澤焦除,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布座韵,位于F島的核電站,受9級特大地震影響踢京,放射性物質(zhì)發(fā)生泄漏誉碴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一瓣距、第九天 我趴在偏房一處隱蔽的房頂上張望黔帕。 院中可真熱鬧,春花似錦蹈丸、人聲如沸成黄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奋岁。三九已至思瘟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間闻伶,已是汗流浹背滨攻。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蓝翰,地道東北人光绕。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像畜份,于是被迫代替她去往敵國和親诞帐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容