SpringBoot 自定義註解使用

  1. 在SpringBoot的框架中,存在着許多的註解,每一個註解爲我們減少了許多的代碼,同時,在項目開發中,我們也可以像SpringBoot一樣,使用屬於自己的註解。
  2. @Target
    @Target說明了Annotation所修飾的對象範圍:Annotation可被用於 packages、types(類、接口、枚舉、Annotation類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循環變量、catch參數)。在Annotation類型的聲明中使用了target可更加明晰其修飾的目標。
public enum ElementType {
    /**用於描述類、接口(包括註解類型) 或enum聲明 Class, interface (including annotation type), or enum declaration */
    TYPE,
 
    /** 用於描述域 Field declaration (includes enum constants) */
    FIELD,
 
    /**用於描述方法 Method declaration */
    METHOD,
 
    /**用於描述參數 Formal parameter declaration */
    PARAMETER,
 
    /**用於描述構造器 Constructor declaration */
    CONSTRUCTOR,
 
    /**用於描述局部變量 Local variable declaration */
    LOCAL_VARIABLE,
 
    /** Annotation type declaration */
    ANNOTATION_TYPE,
 
    /**用於描述包 Package declaration */
    PACKAGE,
 
    /**
     * 用來標註類型參數 Type parameter declaration
     * @since 1.8
     */
    TYPE_PARAMETER,
 
    /**
     *能標註任何類型名稱 Use of a type
     * @since 1.8
     */
    TYPE_USE

列出一個例子

@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface TypeParameterAnnotation {
     
}
 
// 如下是該註解的使用例子
public class TypeParameterClass<@TypeParameterAnnotation T> {
    public <@TypeParameterAnnotation U> T foo(T t) {
        return null;
    }   
}

ElementType.TYPE_USE(Use of a type) 能標註任何類型名稱,包括上面這個(ElementType.TYPE_PARAMETER的):

public class TestTypeUse {
 
    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface TypeUseAnnotation {
         
    }
     
    public static @TypeUseAnnotation class TypeUseClass<@TypeUseAnnotation T> extends @TypeUseAnnotation Object {
        public void foo(@TypeUseAnnotation T t) throws @TypeUseAnnotation Exception {
             
        }
    }
     
    // 如下註解的使用都是合法的
    @SuppressWarnings({ "rawtypes", "unused", "resource" })
    public static void main(String[] args) throws Exception {
        TypeUseClass<@TypeUseAnnotation String> typeUseClass = new @TypeUseAnnotation TypeUseClass<>();
        typeUseClass.foo("");
        List<@TypeUseAnnotation Comparable> list1 = new ArrayList<>();
        List<? extends Comparable> list2 = new ArrayList<@TypeUseAnnotation Comparable>();
        @TypeUseAnnotation String text = (@TypeUseAnnotation String)new Object();
        java.util. @TypeUseAnnotation Scanner console = new java.util.@TypeUseAnnotation Scanner(System.in);
    }
}
  1. @Retention
    定義註解的生命週期,分爲以下三種
/*源碼級別*/
// Annotations are to be discarded by the compiler.
SOURCE,
/*編譯期級別*/
/*Annotations are to be recorded in the class file by the compiler,but need not be retained by the VM at run time.  This is the defaultbehavior.*/
CLASS,
/*運行期級別*/
/*Annotations are to be recorded in the class file by the compiler and retained by the VM at run time, so they may be read reflectively.
RUNTIME

註解@Retention可以用來修飾註解,是註解的註解,稱爲元註解。
Retention註解有一個屬性value,是RetentionPolicy類型的,Enum RetentionPolicy是一個枚舉類型,
這個枚舉決定了Retention註解應該如何去保持,也可理解爲Rentention 搭配 RententionPolicy使用。RetentionPolicy有3個值:CLASS RUNTIME SOURCE
按生命週期來劃分可分爲3類:
1、RetentionPolicy.SOURCE:註解只保留在源文件,當Java文件編譯成class文件的時候,註解被遺棄;
2、RetentionPolicy.CLASS:註解被保留到class文件,但jvm加載class文件時候被遺棄,這是默認的生命週期;
3、RetentionPolicy.RUNTIME:註解不僅被保存到class文件中,jvm加載class文件之後,仍然存在;
這3個生命週期分別對應於:Java源文件(.java文件) —> .class文件 —> 內存中的字節碼。
那怎麼來選擇合適的註解生命週期呢?
首先要明確生命週期長度 SOURCE < CLASS < RUNTIME ,所以前者能作用的地方後者一定也能作用。
一般如果需要在運行時去動態獲取註解信息,那隻能用 RUNTIME 註解,比如@Deprecated使用RUNTIME註解
如果要在編譯時進行一些預處理操作,比如生成一些輔助代碼(如 ButterKnife),就用 CLASS註解;
如果只是做一些檢查性的操作,比如 @Override 和 @SuppressWarnings,使用SOURCE 註解。

註解@Override用在方法上,當我們想重寫一個方法時,在方法上加@Override,當我們方法的名字出錯時,編譯器就會報錯
註解@Deprecated,用來表示某個類或屬性或方法已經過時,不想別人再用時,在屬性和方法上用@Deprecated修飾
註解@SuppressWarnings用來壓制程序中出來的警告,比如在沒有用泛型或是方法已經過時的時候

  1. @Documented
    Documented 註解表明這個註解應該被 javadoc工具記錄. 默認情況下,javadoc是不包括註解的. 但如果聲明註解時指定了 @Documented,則它會被 javadoc 之類的工具處理, 所以註解類型信息也會被包括在生成的文檔中,是一個標記註解,沒有成員。
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {
    public String name() default "fieldName";
    public String setFuncName() default "setField";
    public String getFuncName() default "getField"; 
    public boolean defaultDBValue() default false;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章