Java中的註解-自定義註解

我又不是架構師發表於2019-03-04

Java中的註解-自定義註解

Hello,大家好,好久沒有更了,看到上篇博文裡有人說到讓我快點更Spring系列部落格,這樣就可以不用買書了。這裡我覺得有責任和大家說一下,千萬不要有隻看部落格不看書的習慣,很多人覺得部落格來得快,學的快,緊抓重點。我承認,看部落格是快速入門的一種方式,當然你的選好部落格,老實說,作者自愧不如,真心只是懂點皮毛,很多東西都是拾人牙慧。很多東西也處於學習階段。而且作者有很多知識也不見得全是對的,僅供大家參考。 其實真正想把一系列只是學透徹,作者還是強烈推薦看書的,看一些淘寶,京東的架構寫的書,雖然來的慢,但是很全面,很系統。如果把部落格看做是吃飯時的菜的話,那麼看書無疑就是我們的主食大米了,有點養生常識的都知道,吃主食大米或者麵食才是最補身體的。好了,扯了這麼多,這一篇準備把Java中的自定義註解分享一下子,因為我身邊好多小夥伴,貌似很多都不知道註解這個東西到底是什麼,只知道怎麼用,確不知道註解的底層原理。這一篇就和大家分享一下,文章結構:

  1. Java中的註解概述
  2. 四種元註解
  3. 自定義註解

1. Java中的註解概述

首先要說明一個東西,註解這個東西絕對不是Spring為我們提供的,而是JDK帶的,JDK自己也是有很多內建註解的,比如@override. 註解的功能其實就是為一些加了註解的類,方法等賦予特殊的含義,具體如何產生自定義的含義,其實就是註解處理器了,這是下一篇和大家講的.

2. 四種元註解

元註解,說白了,就是JDK自帶的註解,這些註解是幹嘛的呢?其實就是在我們自定義註解時,註解到我們自定義的註解上的,舉個例子:

@Target(ElementType.TYPE)
public @interface Table {
    public String tableName() default "className";
}
複製程式碼

大家先不要管語法,Table其實就是我自定義的一個註解,可以@Table這樣使用了,那麼這個@Target其實就是元註解了。JDK自帶的元註解如下:

  1. @Target
  2. @Retention
  3. @Documented
  4. @Inherited
@Target

用於描述註解的使用範圍,有一個列舉ElementType來指定,具體如下:

  1. CONSTRUCTOR:用於描述構造器
  2. FIELD:用於描述域
  3. LOCAL_VARIABLE:用於描述區域性變數
  4. METHOD:用於描述方法
  5. PACKAGE:用於描述包
  6. PARAMETER:用於描述引數
  7. TYPE:用於描述類、介面(包括註解型別) 或enum宣告

eg:

@Target(ElementType.METHOD)
public @interface Dog {
    
}
複製程式碼

大家可以看到,我這個Dog註解,只能用到方法上面 。

2. @Retention

表示需要在什麼級別儲存該註釋資訊,用於描述註解的生命週期,也是一個列舉RetentionPoicy來決定的,這個列舉我不列出來了,包括這個註解的具體怎麼決定註解的生命週期我也不多講,因為根據小弟這麼多年使用的經驗,都是填的RetentionPoicy.RUNTIME,填這個值註解處理器才能通過反色拿到註解資訊,實現自己的語義,所以大家都填RetentionPoicy.RUNTIME就可以了,想擴充套件瞭解的自行google..

3. @Documented

如果用javadoc生成文件時,想把註解也生成文件,就帶這個。(話說老鐵們都是怎麼寫文件的,小弟表示從不寫文件… ^_^)

4. @Inherited

@Inherited 元註解是一個標記註解,@Inherited闡述了某個被標註的型別是被繼承的。如果一個使用了@Inherited修飾的annotation型別被用於一個class,則這個annotation將被用於該class的子類。注意,@Inherited annotation型別是被標註過的class的子類所繼承。類並不從它所實現的介面繼承annotation,方法並不從它所過載的方法繼承annotation。

其實這幾個註解只有一個有點用,就是@Target,大家稍微注意下就行了。註解不是你想加哪就加哪的

3. 自定義註解

上面把元註解說了,來講下如何自定義註解,順帶提一下,自定義的註解又叫組合註解.然後說下自定義註解格式:

Java中的註解-自定義註解
  1. 固定格式,不要搞事.
  2. 只能用public或預設(default)這兩個訪問權修飾.例如,String value();這裡把方法設為defaul預設型別;
  3. 定義註解引數的型別,只能為:
  • 所有基本資料型別(int,float,boolean,byte,double,char,long,short)
  • String型別
  • Class型別
  • enum型別
  • Annotation型別
  • 以上所有型別的陣列
  1. 方法名,就是這個註解的支援的屬性名,像常見的value.
  2. 表示該屬性名在不指定時的預設值,可以不要。

好了,我舉個例子:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Dog {
    public String dog() default "";
}
複製程式碼

我定義了一個Dog註解,它有一個屬性為dog,是String型別的,預設值為””.我在使用的時候可以這樣使用,@Dog(dog=”小黃”),還可以直接這樣使用@Dog,不指定dog屬性,預設就是”” .

好了,大家可以看到,這樣就定義了一個註解了,大家可能好奇,這樣有個毛用,我就是加到了具體的類上,也沒什麼鳥用啊。我這裡和大家分享下自己的一點經驗,自定義註解有兩種用法:

  1. 自定義註解處理器專門為你自定義的註解實現語義(比如加了@Dog註解的方法,在呼叫的時候,全部都列印出呼叫資訊到日誌系統) ,後一篇部落格講自定義註解處理器。
  2. 配合Spring使用.

在講如何配合Spring使用前,先說一個知識點,大家可能會忽略掉,那就是註解是可以組合的,如上圖,在自定義註解時,不僅可以加元註解,還可以加其他自定義註解 。這就好玩了,我舉個例子:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Dog {
    public String dog() default "";
}
複製程式碼

我為剛剛的@Dog註解加了@Component,那麼這個註解就會有@Component的功能了(被Spring當做bean加入到Spring容器裡).現在在順帶說下屬性修飾符public和預設的區別

  • public修飾的屬效能被覆蓋,預設的則不能.
    舉個例子:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
@Dog
public @interface StupidDog {
    public String dog() default "我是一條StupidDog";
}
複製程式碼

我現在又定義了一個StupidDog註解,這個註解覆蓋掉了@Dog的dog屬性,把預設值從””改成了”我是一條StupidDog”..

好了,回到話題上,知道了組合註解可以擁有被註解的註解的功能,還拿剛才那個加了@Component註解的@Dog註解來說,當某個類被加了這個註解,比如:

@Dog
public class TestService {
    ...
}
複製程式碼

我們知道這個TestService在Spring的環境下會被加到Spring容器裡成為Bean,可是這有什麼鳥用了?這個作用可大了!這可以把Spring容器裡的bean區分開來,比如如下程式碼片段:

// ctx 為Spring的ApplicationContext
// // 獲取所有帶有 Dog 註解的 Spring Bean
Map<String, Object> serviceBeanMap = ctx.getBeansWithAnnotation(Dog.class); 
複製程式碼

大家可以看到,可以通過ApplicationContext取到一些帶有特殊標記(自定義註解)的Spring bean! 大家不要小看了這一功能,如果你想在Spring容器初始化完畢後,對某一類Spring Bean做一些特殊操作。自定義註解可以幫你區分開來。

結語

好了,自定義註解的一些知識就和大家分享完了,其實比較簡單,語法也很清晰,然後又提了下運用組合註解的知識來結合Spring的@Componenet使用,截止到目前為止,大家會發現自己定義的註解,除了能和Spring結合用一下子,並沒什麼鳥用,上面也提到了,目前為止是的,下一篇給大家分享下自定義註解處理,這個東西可以讓我們自定義的註解實現自己特有的功能。今天週五,大家週末愉快,多出去打個野。少加班,保重龍體,幹it的,別和需求過不去,能推就推。Over,Have a good day .

相關文章