Java 注解基礎

1. 注解(Annotation)

  • JDK1.5 以后版本引入的一個特性
  • 可以被其他程序(比如:編譯器)讀取
  • 語法 @注釋名

2. 內置注解

  • @Override
    • 標記重寫父類方法
  • @Deprecated
    • 標記過時方法,表示不建議再使用
  • @SuppressWarnings
    • 抑制編譯時的警告信息
    • 需要添加參數才能正常使用,例如 @SuppressWarnings("unchecked")

3. 元注解(meta-annotation)

  • 作用:注解其他注解
  • 定義了 4 個標準的 meta-annotation 類型,用來對其他類型作說明
    • @Target
    • @Retention
    • @Documented
    • @Inherited

3.1 @Target

  • Indicates the contexts in which an annotation type is applicable
public enum ElementType {
    TYPE,
    FIELD,
    METHOD,
    PARAMETER,
    CONSTRUCTOR,
    LOCAL_VARIABLE,
    ANNOTATION_TYPE,
    PACKAGE,
    TYPE_PARAMETER,
    TYPE_USE
}

3.2 @Retention

  • 描述注解的生命周期
  • SOURCE < CLASS < RUNTIME
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}

public enum RetentionPolicy {
    // 保留在源碼階段,編譯時被丟棄
    SOURCE,
    // 保留到編譯進行時的class文件,但 JVM 加載class文件時候被遺棄
    CLASS,
    // 保留到程序運行時
    RUNTIME
}

3.3 @Documented

  • 將被記錄在 javadoc 中

3.4 @Inherited

  • 子類可以繼承父類的注解

4. 自定義注解

  • 定義注解用 @interface, 注解中只能包含屬性
  • 里面的方法實際上是聲明的屬性,方法名稱就是屬性名稱,返回值類型就是屬性的類型
  • 若只有一個屬性,一般名為 value
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EntryLog {
  // 屬性 value
  String value() default "";
  String[] codes() default {};
}

若屬性沒有默認值,必須給注解賦值

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EntryLog {
  String value() default "";
  String[] codes();
}
// 需給注解賦值
@EntryLog(codes = {"1001", "1002"})

4.1 注解屬性類型

  • 基本數據類型
  • String 類型
  • Class 類型
  • 枚舉類型
  • 注解類型
  • 以上類型的一維數組

數組用 {} 來存儲,當數組中只有一個值時可省略 {}

// 數組類型 String[] codes();
@EntryLog(codes = "1001")
@EntryLog(codes = {"1001", "1002"})

// 枚舉數組類型  ElementType[] value();
@Target(ElementType.TYPE)
@Target({ElementType.TYPE, ElementType.METHOD})

4.2 反編譯文件

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface EntryLog {
    int num() default 0;
    String value();
    // Class 類型
    Class<?> clazz();
    // 枚舉類型
    CodeEnum codeEnum();
    // 注解類型
    DemoAnno demoAnno();
}
// 自動繼承 java.lang.annotation.Annotation 接口
public interface EntryLog extends java.lang.annotation.Annotation {
  public abstract int num();
  public abstract java.lang.String value();
  public abstract java.lang.Class<?> clazz();
  public abstract com.example.concrete.CodeEnum codeEnum();
  public abstract com.example.concrete.DemoAnno demoAnno();
}
public interface Annotation {
  boolean equals(Object obj);
  int hashCode();
  String toString();
  Class<? extends Annotation> annotationType();
}

5. Spring 注解 @AliasFor

  • @AliasFor 用于聲明注釋屬性別名

同一個注解中的兩個屬性互為別名
例如:@ComponentScan 注解中,value 和 basePackages 兩個屬性互為別名

public @interface ComponentScan {
    @AliasFor("basePackages")
    String[] value() default {};

    @AliasFor("value")
    String[] basePackages() default {};
}

跨注解的屬性別名
例如:@Service#value的值可以映射到@Component#value

public @interface Service {
    @AliasFor(annotation = Component.class)
    String value() default "";
}
public @interface Component {
    String value() default "";
}

5.1 @SpringBootApplication 分析

public @interface SpringBootApplication {
    @AliasFor(annotation = EnableAutoConfiguration.class)
    Class<?>[] exclude() default {};

    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};
}

其他

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容