java反射機制的定義:java
在運行轉態時(動態的)時。web
對於任意一個類,都可以知道這個類的全部屬性和方法spring
對於任意一個對象,都可以知道調用它的任意屬性和方法api
java中用對象來對現實生活中的事物進行抽象,如人(現實生活)抽象到一個person類(java對象)。但有沒有想過,java中的類(現實生活)其實也是一個Class對象(對象)。所以,這個Class類就包含了全部你定義的Class信息,包括全部的方法(私有,公有)、構造器、實現了那些方法、哪些註解信息、全部的屬性等相關的信息,它還提供newInstance()方法來生成實例。安全
Class對象是一個至關特殊的對象,是一個超泛化的對象,是全部對象的對象。所以智能由JVM在建立其餘對象的時候自動建立,所以Class對象又稱包含了其餘對象的字節碼的信息的對象。app
Class類是反射機制的起源,咱們獲得Class類對象有3種方法:框架
第一種:經過類名得到ide
Class<?> class = ClassName.class;工具
第二種:經過類名全路徑得到:ui
Class<?> class = Class.forName("類名全路徑");
第三種:經過實例對象得到:
Class<?> class = object.getClass();
總結:第一種方法:類字面常量使得建立Class對象的引用時不會自動地初始化該對象,而是按照以前提到的加載,連接,初始化三個步驟,這三個步驟是個懶加載的過程,不使用的時候就不加載。
第二種方法:Class類自帶的方法。
第三種方法:是全部的對象都可以使用的方法,由於getClass()方法是Object類的方法,全部的類都繼承了Object,所以全部類的對象也都具備getClass()方法。
建議:使用類名.class,這樣作即簡單又安全,由於在編譯時就會受到檢查,所以不須要置於try語句塊中,而且它根除了對forName()方法的調用,因此也更高效。
看完反射的定義,咱們就知道,反射機制就是增長了程序的靈活性,最重要的用途就是來開發通用型的框架,如Spring,將全部類的bean交給spring容器管理。不管是XML配置仍是註解配置,當咱們獲取bean時,容器都會讀取配置,這些配置就是類的信息,容器根據反射,生成實例返回。具體的做用還有動態代理、切面邏輯等等,其本質就是反射。
註解(Annotation)就是Java提供了一種元程序中的元素關聯任何信息或者任何元數據(metadata)的途徑和方法,Annotation(註解)是一個接口,程序能夠經過放射來獲取指定的程序元素的Annotation對象,而後經過Annotation對象來獲取註解裏面的元數據。
Annotation能被用來爲某個程序元素(類、方法、成員變量等)關聯任何的信息。須要注意的是,這裏存在着一個基本的規則:Annotation不能影響程序代碼的執行,不管增長、刪除Annotation,代碼都始終如一的執行;另外,儘管一些annotation經過java的放射api方法在運行時被訪問,而java語言解釋器在工做時忽略了這些annotation。正是因爲java虛擬機忽略了annotation,致使了annotation類型在代碼中「不起做用」的;只有經過某種配套的工具纔會對annotation類型中的信息進行訪問和處理。
元數據從metadata一詞譯來,就是「關於數據的數據」的意思。
元數據的功能做用有不少,好比:你可能用過Javadoc的註釋自動生成文檔。這就是元數據功能的一種。總的來講,元數據能夠用來建立文檔,跟蹤代碼的依賴性,執行編譯時格式檢查,代替已有的配置文件。若是要對於元數據的做用進行分類,目前尚未明確的定義,不過咱們能夠根據它所起的做用,大體可分爲三類:
1. 編寫文檔:經過代碼裏標識的元數據生成文檔
2. 代碼分析:經過代碼裏標識的元數據對代碼進行分析
3. 編譯檢查:經過代碼裏標識的元數據讓編譯器能實現基本的編譯檢查
在Java中元數據以標籤的形式存在於Java代碼中,元數據標籤的存在並不影響程序代碼的編譯和執行,它只是被用來生成其它的文件或針在運行時知道被運行代碼的描述信息。
綜上所述:
第一,元數據以標籤的形式存在於Java代碼中。
第二,元數據描述的信息是類型安全的,即元數據內部的字段都是有明確類型的。
第三,元數據須要編譯器以外的工具額外的處理用來生成其它的程序部件。
第四,元數據能夠只存在於Java源代碼級別,也能夠存在於編譯以後的Class文件內部。
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說明了Annotation所修飾的對象範圍。取值(ElementType)有
1.CONSTRUCTOR:用於描述構造器
2.FIELD:用於描述域
3.LOCAL_VARIABLE:用於描述局部變量
4.METHOD:用於描述方法
5.PACKAGE:用於描述包
6.PARAMETER:用於描述參數
7.TYPE:用於描述類、接口(包括註解類型) 或enum聲明
@Retention定義了該Annotation被保留的時間長短,如某些Annotation僅出如今源碼中,而被編譯器丟棄。取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在運行時有效(即運行時保留)
屬性值是RUTIME,這樣註解處理器能夠經過反射,獲取到該註解的屬性值,從而去作一些運行時的邏輯處理屬性值是RUTIME,這樣註解處理器能夠經過反射,獲取到該註解的屬性值,從而去作一些運行時的邏輯處理
@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修飾的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 {}; }