Java註解實現機制

2020-09-20 04:00:13

理解Java註解實現機制

前言

在Spring 2.0及早期時代,Java 還沒引入註解,這個時候如果我們要在 Spring 中宣告一個 Bean,我們只能通過 XML 設定的方式,Web專案開發都是通過組態檔 xml來實現 Bean 的依賴注入,有多少個Bean,就在xml設定中加多少個,這樣一來在 Bean 的數量越來越多的時候,xml的設定也就會越來越複雜,顯得格外的冗餘,Spring 2.0 在xml組態檔上做了一定的優化,讓設定看起來越來越簡單。
而在後來的 Spring 3.0 時代,可以使用 Spring 提供的 Java 註解來取代曾經 xml 設定上的所產生的問題,Spring 使得專案開發設定變得簡單了許多

一,什麼是註解?

.註解其實就是程式碼裡的特殊標記 ,這些標記可以在編譯,類載入,執行時被讀取,並執行相應的處理。通過使用註解,程式設計師可以在不改變原有邏輯的情況下 ,在原始檔中嵌入一些補充資訊。程式碼分析工具,開發工具和部署工具可以通過這些補充資訊進行驗證或者進行部署

二, 註解有何用?

1,註解的出現極大的簡化了jdk1.5之前 使用xml設定的方式,代替JavaEE舊版中所遺留的繁冗程式碼和XML設定等
2,生產檔案註解,標明該模組類開發者,模組版本等資訊。
3,在編譯時進行格式檢查(Jdk內建的三個基本註解)
在這裡插入圖片描述
4,跟蹤程式碼依賴性,實現替代組態檔等功能
範例
xml設定方式

public class DemoService{
}
<bean id="demoService" class="com.lulu.DemoService"/>

註解設定方式

@Service
public class DemoService{
}

三,註解重要麼?

未來的開發模式都是基於註解的,JPA是基於註解的,Spring2.5以上是基於註解的,現在的springboot是完全註解開發,註解是一種趨勢,一定程度上可以說:框架=註解+反射+設計模式。

四,如何自定義註解?

1:
在定義註解之前我們可以看看註解的原始碼是怎樣定義的
我們可以通過idea的快捷鍵選中註解 按住Crtl同時點選滑鼠左鍵檢視註解原始碼
如 選中select()上的 @Override

  @Override
    public List<Admin> select() {
        return adminMapper.select();
    }
}

2:
然後我們就看到了原始碼對@Override的定義,可以發現這和介面的定義很像,都有通過interface進行宣告,只不過interface多了一個@
還有兩個對註解的註解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

3:
然後我們可以參照此註解自定義註解,首先使用@interface關鍵字(自定義的註解自動繼承了java.lang.annotation.Annotation介面),我們可以給該註解加入一個成員引數屬性 value ,注意,雖然value有一對括號,和類,介面的方法定義很像 但它是註解的屬性不是方法

/**
* @author Tony-wang
* @create 2020-09-17-16:05
*/
public @interface MyAnnotation {
   String value()
}

4:
然後我們就可以在其它類或方法上使用自定義註解了
注意 宣告註解成員後 如果沒有指定預設值default就要 在使用註解時 顯示的賦值 ,如果不宣告內部成員,那麼該註解僅起到一個標識作用,如@Override就沒有內部成員

@MyAnnotation("hello")
public class Person{

五:元註解

1:什麼是元註解呢?

元註解 是jdk中修飾其他註解的註解,jdk1.5中提供了4種標準的meta-annotation型別 分別是 Retention Target Document Inherited

Retention:只能用於修飾一個Annotation定義,用於指定該Annotation的生命週期,該元註解包含一個RetentionPolicy型別的成員變數,使用@Rentention必須為該value賦值
RetentionPolicy有三個狀態
RetentionPolicy.SOURCE:在原始檔中有效(編譯器直接丟棄這種策略的註釋)

RetentionPolicy.CLASS:在class檔案中有效,當執行java程式時,jvm不會保留註釋,這是預設值

RetentionPolicy.RUNTIME:在執行時有效(即執行中保留),當執行java程式時,jvm會保留註釋,程式可以通過反射獲取該註釋 *

Target 用於修飾該註解可以在哪些地方進行使用 指定類 中使用還是介面使用還是區域性變數進行使用

如 該註解就只能在屬性和方法中使用

@Target({FIELD,METHOD})//表示該註解只能使用在屬性和方法上
@Retention(RetentionPolicy.RUNTIME)//執行時有效,被jvm類載入器載入到記憶體後 可以通過反射獲取註解資訊
public @ interface MyAnnotation{

Document :用於指定該註解會被javadoc 工具提取為檔案(很少用)
Inherited:被它修飾的註解具有基礎性(很少用)

Java 1.8中註解增強

元註解@Repeatable
元註解@Repeatable是JDK1.8新加入的,它表示在同一個位置重複相同的註解。在沒有該註解前,一般是無法在同一個型別上使用相同的註解的

//Java8前無法這樣使用
@FilterPath("/web/update")
@FilterPath("/web/add")
public class A {}

但在Java8新增了@Repeatable註解後就可以採用如下的方式定義並使用了

//使用Java1.8新增@Repeatable元註解
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(FilterPaths.class)//引數指明接收的註解class
public @interface FilterPath {
    String  value();
}

//使用案例
@FilterPath("/web/add")
@FilterPath("/web/delete")
class AA{ }

JDK1.8新增兩個列舉元
在Java8中 ElementType 新增兩個列舉元,TYPE_PARAMETER 和 TYPE_USE ,在Java1.8前註解只能標註在一個宣告(如欄位、類、方法)上,Java8後,新增的TYPE_PARAMETER可以用於標註型別引數,而TYPE_USE則可以用於標註任意型別(不包括class)。如下TYPE_USE修飾泛型型別,異常型別,強轉型別所示

@Target({FIELD,METHOD,TYPE_PARAMETER,TYPE_USE})//
@Retention(RetentionPolicy.RUNTIME)//執行時有效,被jvm類載入器載入到記憶體後 可以通過反射獲取註解資訊
public @ interface MyAnnotation{
string value() default "HEELO 靚仔!"
}

class Generic<@MyAnnotation T>{  //註解修飾泛型型別
   public void show() throws @MyAnnotation RuntimeException{//註解修飾異常型別
   ArrayList<@MyAnnotation String> list = new ArrayList<>();
   int num = (@MyAnnotation int ) 10L;//對強轉型別進行修飾
   }