1. 程式人生 > >簡談Java 反射機制,動態代理

簡談Java 反射機制,動態代理

也有 object 持久化數據 多場景 字節 問控制 事情 獲取 ted

談談 Java 反射機制,動態代理是基於什麽原理?小編整理了一些java進階學習資料和面試題,需要資料的請加JAVA高階學習Q群:701136382 這是小編創建的java高階學習交流群,加群一起交流學習深造。群裏也有小編整理的2019年最新最全的java高階學習資料!

反射機制

Java 語言提供的一種基礎功能,賦予程序在運行時自省(introspect,官方用語)的能力。可以在運行時通過提供完整的“包名+類名.class”得到某個對象的類型。

功能

在運行時能判斷任意一個對象所屬的類。

在運行時能構造任意一個類的對象。

在運行時判斷任意一個類所具有的成員變量和方法。

在運行時調用任意一個對象的方法。

利用Java反射機制我們可以加載一個運行時才得知名稱的 class,獲悉其構造方法,並生成其對象實體,能對其 fields 設值並喚起其methods。

應用場景

通過反射我們可以直接操作類或者對象,比如獲取某個對象的類定義,獲取類聲明的屬性和方法,調用方法或者構造對象,甚至可以運行時修改類定義。

通過運行時操作元數據或對象,Java 可以靈活地操作運行時才能確定的信息。

反射技術常用在各類通用框架開發中。因為為了保證框架的通用性,需要根據配置文件加載不同的對象或類,並調用不同的方法,這個時候就會用到反射——運行時動態加載需要加載的對象。

特點:

由於反射會額外消耗一定的系統資源,因此如果不需要動態地創建一個對象,那麽就不需要用反射。另外,反射調用方法時可以忽略權限檢查,因此可能會破壞封裝性而導致安全問題。

動態代理

一種方便運行時動態構建代理、動態處理代理方法調用的機制。為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在兩者之間起到中介的作用(可類比房屋中介,房東委托中介銷售房屋、簽訂合同等)。

所謂動態代理,就是實現階段不用關心代理誰,而是在運行階段才指定代理哪一個對象(不確定性)。如果是自己寫代理類的方式就是靜態代理(確定性)。

組成要素:

1、抽象類接口

2、被代理類(具體實現抽象接口的類)

3、動態代理類:實際調用被代理類的方法和屬性的類

應用場景

很多場景都是利用類似機制做到的,比如用來包裝 RPC 調用、面向切面的編程(AOP)。其是反射延伸出來的一種廣泛應用於產品開發中的技術,很多繁瑣的重復編程,都可以被動態代理機制優雅地解決

實現方式

1、JDK 自身提供的動態代理,主要利用了反射機制。

2、利用傳更高性能的字節碼操作機制,類似 ASM、cglib(基於 ASM)、Javassist 等。

舉例,常可采用的 JDK 提供的動態代理接口InvocationHandler 來實現動態代理類。其中 invoke 方法是該接口定義必須實現的,它完成對真實方法的調用。通過 InvocationHandler 接口,所有方法都由該 Handler 來進行處理,即所有被代理的方法都 InvocationHandler 接管實際的處理任務。此外,我們常可以在 invoke 方法實現中增加自定義的邏輯實現,實現對被代理類的業務邏輯無侵入。

知識擴展:

代理模式(通過代理靜默地解決一些業務無關的問題,比如遠程、安全、事務、日誌、資源關閉……讓應用開發者可以只關心他的業務)

靜態代理:事先寫好代理類,可以手工編寫,也可以用工具生成。缺點是每個業務類都要對應一個代理類,非常不靈活。

動態代理:運行時自動生成代理對象。缺點是生成代理代理對象和調用代理方法都要額外花費時間。

JDK 動態代理:基於 Java 反射機制實現,必須要實現了接口的業務類才能用這種辦法生成代理對象。新版本也開始結合 ASM 機制。

cglib 動態代理:基於 ASM 機制實現,通過生成業務類的子類作為代理類。

Java 反射機制的常見應用:動態代理(AOP、RPC)、提供第三方開發者擴展能力(Servlet 容器,JDBC 連接)、第三方組件創建對象(DI)等等

反射機制:

反射提供了 AccessibleObject.setAccessible?(boolean flag)。它的大多數子類重寫了這個方法,這裏的所謂 accessible 可以理解成修飾成員的 public、protected、private,這意味著我們可以在運行時修改成員訪問限制!

setAccessible 的應用場景:

1、我們為一個 Java 實體對象,運行時自動生成 setter、getter 的邏輯,這是加載或者持久化數據非常必要的,框架通常可以利用反射做這個事情,而不需要開發者手動寫類似的重復代碼。

2、繞過 API 訪問控制。我們日常開發時可能被迫要調用內部 API 去做些事情,比如,自定義的高性能 NIO 框架需要顯式地釋放 DirectBuffer,使用反射繞開限制是一種常見辦法。

動態代理:

動態代理解決了什麽問題?

1、它是一個代理機制(代理可以看作是對調用目標的一個包裝)。通過代理,我們對目標代碼的調用不是直接發生的,而是通過代理完成。

2、通過代理可以讓調用者與實現者之間解耦。比如進行 RPC 調用,框架內部的尋址、序列化、反序列化等,對於調用者往往是沒有太大意義的,通過代理,可以提供更加友善的界面。

簡談Java 反射機制,動態代理