java@ 注解原理與使用


Java反射

         java反射機制的定義:

在運行轉態時(動態的)時。

對於任意一個類,都能夠知道這個類的所有屬性和方法

對於任意一個對象,都能夠知道調用它的任意屬性和方法

Class對象

java中用對象來對現實生活中的事物進行抽象,如人(現實生活)抽象到一個person類(java對象)。但有沒有想過,java中的類(現實生活)其實也是一個Class對象(對象)。因此,這個Class類就包含了所有你定義的Class信息,包括所有的方法(私有,公有)、構造器、實現了那些方法、哪些注解信息、所有的屬性等相關的信息,它還提供newInstance()方法來生成實例。

         Class對象是一個相當特殊的對象,是一個超泛化的對象,是所有對象的對象。因此智能由JVM在創建其他對象的時候自動創建,因此Class對象又稱包含了其他對象的字節碼的信息的對象。

反射實現方法

 Class類是反射機制的起源,我們得到Class類對象有3種方法:

  第一種:通過類名獲得

  Class<?> class = ClassName.class;

  第二種:通過類名全路徑獲得:

  Class<?> class = Class.forName("類名全路徑");

  第三種:通過實例對象獲得:

Class<?> class = object.getClass();

 

總結:第一種方法:類字面常量使得創建Class對象的引用時不會自動地初始化該對象,而是按照之前提到的加載,鏈接,初始化三個步驟,這三個步驟是個懶加載的過程,不使用的時候就不加載。

   第二種方法:Class類自帶的方法。

   第三種方法:是所有的對象都能夠使用的方法,因為getClass()方法是Object類的方法,所有的類都繼承了Object,因此所有類的對象也都具有getClass()方法。

 

建議:使用類名.class,這樣做即簡單又安全,因為在編譯時就會受到檢查,因此不需要置於try語句塊中,並且它根除了對forName()方法的調用,所以也更高效。

反射作用

         看完反射的定義,我們就知道,反射機制就是增加了程序的靈活性,最重要的用途就是來開發通用型的框架,如Spring,將所有類的bean交給spring容器管理。無論是XML配置還是注解配置,當我們獲取bean時,容器都會讀取配置,這些配置就是類的信息,容器根據反射,生成實例返回。具體的作用還有動態代理、切面邏輯等等,其本質就是反射。

 

Java注解相關概念

什么是注解

         注解(Annotation)就是Java提供了一種元程序中的元素關聯任何信息或者任何元數據(metadata)的途徑和方法,Annotation(注解)是一個接口,程序可以通過放射來獲取指定的程序元素的Annotation對象,然后通過Annotation對象來獲取注解里面的元數據。

         Annotation能被用來為某個程序元素(類、方法、成員變量等)關聯任何的信息。需要注意的是,這里存在着一個基本的規則:Annotation不能影響程序代碼的執行,無論增加、刪除Annotation,代碼都始終如一的執行;另外,盡管一些annotation通過java的放射api方法在運行時被訪問,而java語言解釋器在工作時忽略了這些annotation。正是由於java虛擬機忽略了annotation,導致了annotation類型在代碼中“不起作用”的;只有通過某種配套的工具才會對annotation類型中的信息進行訪問和處理。

什么是metadata(元數據)

 元數據從metadata一詞譯來,就是“關於數據的數據”的意思。
  元數據的功能作用有很多,比如:你可能用過Javadoc的注釋自動生成文檔。這就是元數據功能的一種。總的來說,元數據可以用來創建文檔,跟蹤代碼的依賴性,執行編譯時格式檢查,代替已有的配置文件。如果要對於元數據的作用進行分類,目前還沒有明確的定義,不過我們可以根據它所起的作用,大致可分為三類: 
    1. 編寫文檔:通過代碼里標識的元數據生成文檔
    2. 代碼分析:通過代碼里標識的元數據對代碼進行分析
    3. 編譯檢查:通過代碼里標識的元數據讓編譯器能實現基本的編譯檢查
  在Java中元數據以標簽的形式存在於Java代碼中,元數據標簽的存在並不影響程序代碼的編譯和執行,它只是被用來生成其它的文件或針在運行時知道被運行代碼的描述信息。
  綜上所述:
    第一,元數據以標簽的形式存在於Java代碼中。
    第二,元數據描述的信息是類型安全的,即元數據內部的字段都是有明確類型的。
    第三,元數據需要編譯器之外的工具額外的處理用來生成其它的程序部件。
    第四,元數據可以只存在於Java源代碼級別,也可以存在於編譯之后的Class文件內部。

Annotation和Annotation類型:

Annotation:

  Annotation使用了在java5.0所帶來的新語法,它的行為十分類似public、final這樣的修飾符。每個Annotation具有一個名字和成員個數>=0。每個Annotation的成員具有被稱為name=value對的名字和值(就像javabean一樣),name=value裝載了Annotation的信息。

  Annotation類型:

  Annotation類型定義了Annotation的名字、類型、成員默認值。一個Annotation類型可以說是一個特殊的java接口,它的成員變量是受限制的,而聲明Annotation類型時需要使用新語法。當我們通過java反射api訪問Annotation時,返回值將是一個實現了該 annotation類型接口的對象,通過訪問這個對象我們能方便的訪問到其Annotation成員。

注解的分類:

  根據注解參數的個數,我們可以將注解分為三類:
    1.標記注解:一個沒有成員定義的Annotation類型被稱為標記注解。這種Annotation類型僅使用自身的存在與否來為我們提供信息。比如后面的系統注解@Override;
    2.單值注解
    3.完整注解  

根據注解使用方法和用途,我們可以將Annotation分為三類:
    1.JDK內置系統注解
    2.元注解
    3.自定義注解

系統內置標准注解:

注解的語法比較簡單,除了@符號的使用外,他基本與Java固有的語法一致,JavaSE中內置三個標准注解,定義在java.lang中:
    @Override:用於修飾此方法覆蓋了父類的方法;
    @Deprecated:用於修飾已經過時的方法;
    @SuppressWarnnings:用於通知java編譯器禁止特定的編譯警告。

元注解:

  元注解的作用就是負責注解其他注解。Java5.0定義了4個標准的meta-annotation類型,它們被用來提供對其它 annotation類型作說明。Java5.0定義的元注解:
    1.@Target,
    2.@Retention,
    3.@Documented,
    4.@Inherited

@Target

         @Target說明了Annotation所修飾的對象范圍。取值(ElementType)有

    1.CONSTRUCTOR:用於描述構造器
    2.FIELD:用於描述域
    3.LOCAL_VARIABLE:用於描述局部變量
    4.METHOD:用於描述方法
    5.PACKAGE:用於描述包
    6.PARAMETER:用於描述參數
    7.TYPE:用於描述類、接口(包括注解類型) 或enum聲明

@Retention

         @Retention定義了該Annotation被保留的時間長短,如某些Annotation僅出現在源碼中,而被編譯器丟棄。取值(RetentionPoicy)有:

1.SOURCE:在源文件中有效(即源文件保留)
    2.CLASS:在class文件中有效(即class保留)
    3.RUNTIME:在運行時有效(即運行時保留)

屬性值是RUTIME,這樣注解處理器可以通過反射,獲取到該注解的屬性值,從而去做一些運行時的邏輯處理屬性值是RUTIME,這樣注解處理器可以通過反射,獲取到該注解的屬性值,從而去做一些運行時的邏輯處理

@Documented

         @Documented用於描述其他類型的annotation應該被作為被標注的程序成員公共的API,因此可以被例如javadoc此類的工具文檔化。Documented是一個標記注解,沒有成員。

@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;

}

 

@Inherited

@Inherited 元注解是一個標記注解,@Inherited闡述了某個被標注的類型是被繼承的。如果一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。

自定義注解

package annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
    String value() default "";
}

 

四、注解組合使用

Java spring開發時,經常在一個類上有多個注解,如SpringMVC注解

@RestController
@RequestMapping(‘/person’)

可以合並成一個

@PathRestController(‘/person’)

實現是

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
import org.springframework.core.annotation.AliasFor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RestController
@RequestMapping
public @interface PathRestController {
    @AliasFor("path")
    String[] value() default {};
 
    @AliasFor("value")
    String[] path() default {};
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM