java的反射和代理
反射
反射(Reflection)是 Java 程序開發(fā)語言的特征之一,它允許運(yùn)行中的 Java 程序獲取自身的信息,并且可以操作類或?qū)ο蟮膬?nèi)部屬性。
通過反射機(jī)制,可以在運(yùn)行時(shí)訪問 Java 對(duì)象的屬性,方法,構(gòu)造方法等。
反射的應(yīng)用場(chǎng)景
開發(fā)通用框架 - 反射最重要的用途就是開發(fā)各種通用框架。很多框架(比如 Spring)都是配置化的(比如通過 XML 文件配置 JavaBean、Filter 等),為了保證框架的通用性,它們可能需要根據(jù)配置文件加載不同的對(duì)象或類,調(diào)用不同的方法,這個(gè)時(shí)候就必須用到反射——運(yùn)行時(shí)動(dòng)態(tài)加載需要加載的對(duì)象。
動(dòng)態(tài)代理 - 在切面編程(AOP)中,需要攔截特定的方法,通常,會(huì)選擇動(dòng)態(tài)代理方式。這時(shí),就需要反射技術(shù)來實(shí)現(xiàn)了。--所以 代理是反射中的一種
注解 - 注解本身僅僅是起到標(biāo)記作用,它需要利用反射機(jī)制,根據(jù)注解標(biāo)記去調(diào)用注解解釋器,執(zhí)行行為。如果沒有反射機(jī)制,注解并不比注釋更有用。
可擴(kuò)展性功能 - 應(yīng)用程序可以通過使用完全限定名稱創(chuàng)建可擴(kuò)展性對(duì)象實(shí)例來使用外部的用戶定義類
反射的缺點(diǎn)
性能開銷 - 由于反射涉及動(dòng)態(tài)解析的類型,因此無法執(zhí)行某些 Java 虛擬機(jī)優(yōu)化。因此,反射操作的性能要比非反射操作的性能要差,應(yīng)該在性能敏感的應(yīng)用程序中頻繁調(diào)用的代碼段中避免。
破壞封裝性 - 反射調(diào)用方法時(shí)可以忽略權(quán)限檢查,因此可能會(huì)破壞封裝性而導(dǎo)致安全問題。
內(nèi)部曝光 - 由于反射允許代碼執(zhí)行在非反射代碼中非法的操作,例如訪問私有字段和方法,所以反射的使用可能會(huì)導(dǎo)致意想不到的副作用,這可能會(huì)導(dǎo)致代碼功能失常并可能破壞可移植性。反射代碼打破了抽象,因此可能會(huì)隨著平臺(tái)的升級(jí)而改變行為。
反射的過程
正常的類加載過程為:
(1)在編譯時(shí),Java 編譯器編譯好 .java 文件之后,在磁盤中產(chǎn)生 .class 文件。.class 文件是二進(jìn)制文件,內(nèi)容是只有 JVM 能夠識(shí)別的機(jī)器碼。
(2)JVM 中的類加載器讀取字節(jié)碼文件,取出二進(jìn)制數(shù)據(jù),加載到內(nèi)存中,解析.class 文件內(nèi)的信息。類加載器會(huì)根據(jù)類的全限定名來獲取此類的二進(jìn)制字節(jié)流;然后,將字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu);接著,在內(nèi)存中生成代表這個(gè)類的 java.lang.Class 對(duì)象。
(3)加載結(jié)束后,JVM 開始進(jìn)行連接階段(包含驗(yàn)證、準(zhǔn)備、初始化)。經(jīng)過這一系列操作,類的變量會(huì)被初始化。
反射的過程:
要想使用反射,首先需要獲得待操作的類所對(duì)應(yīng)的 Class 對(duì)象。Java 中,無論生成某個(gè)類的多少個(gè)對(duì)象,這些對(duì)象都會(huì)對(duì)應(yīng)于同一個(gè) Class 對(duì)象。這個(gè) Class 對(duì)象是由 JVM 生成的,通過它能夠獲悉整個(gè)類的結(jié)構(gòu)。所以,java.lang.Class 可以視為所有反射 API 的入口點(diǎn)。
反射的本質(zhì)就是:在運(yùn)行時(shí),把 Java 類中的各種成分映射成一個(gè)個(gè)的 Java 對(duì)象。
代理
代理是反射中的一種
動(dòng)態(tài)代理常被用于一些 Java 框架中。例如 Spring 的 AOP ,Dubbo 的 SPI 接口,就是基于 Java 動(dòng)態(tài)代理實(shí)現(xiàn)的。
靜態(tài)代理
靜態(tài)代理其實(shí)就是指設(shè)計(jì)模式中的代理模式。
代理模式為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。
動(dòng)態(tài)代理
動(dòng)態(tài)代理是基于兩個(gè)重要的類(接口),一個(gè)是 InvocationHandler 接口、另一個(gè)則是 Proxy 類,這一個(gè)類和一個(gè)接口是實(shí)現(xiàn)我們動(dòng)態(tài)代理所必須用到的。
有關(guān)動(dòng)態(tài)代理可以看看我的另外一篇博客-【java常用的設(shè)計(jì)模式】

浙公網(wǎng)安備 33010602011771號(hào)