今天在單位沒事看JAVA核心知識點的時候看到了AOP的講解部分,正好有講解AOP動態代理章節順便就參考一下其他資料 和API 寫了一下例子分享一下。
說到動態代理就要從靜態代理開始說起:
靜態代理:
靜態代理程序運行前就已經存在代理類的字節碼文件,代理類和委託類的關係早已確定好了。具體了代碼示例我就不寫了。
靜態代理類的優缺點:
優點:只關心自己的業務類。附加功能有代理類完成。
缺點:1、代理對象的一個接口只服務一種類型的對象。程序規模變大將無法勝任了。
2、接口增加方法,實現類也要增加方法,所有代理類都將修改。
問題引申:靜態代理需要委託類已存在且知曉,而是先不知的委託類靜態代理將無法實現。此時我們就將需要動態代理。
動態代理類圖:
動態代理類定義:
動態代理類(以下簡稱為代理類)是一個實現在創建類時在運行時指定的接口列表的類,該類具有下面描述的行為。 代理接口 是代理類實現的一個接口。 代理實例 是代理類的一個實例。 每個代理實例都有一個關聯的調用處理程序 對象,它可以實現接口 InvocationHandler。通過其中一個代理接口的代理實例上的方法調用將被指派到實例的調用處理程序的 Invoke 方法,並傳遞代理實例、識別調用方法的 java.lang.reflect.Method 對象以及包含參數的 Object 類型的數組。調用處理程序以適當的方式處理編碼的方法調用,並且它返回的結果將作為代理實例上方法調用的結果返回。
Spring實現動態代理方式:
Spring提供了兩種方式來生成代理對象: JDKProxy和Cglib,具體使用哪種方式生成由AopProxyFactory根據AdvisedSupport對象的配置來決定。默認的策略是如果目標類是接口,則使用JDK動態代理技術,否則使用
Cglib來生成代理。 本片只探究 JDKProxy實現。JDK動態接口代理
JDK動態代理主要涉及到java.lang.reflect包中的一個類:Proxy和一個接口InvocationHandler。通過實現該接口定義橫切邏輯,並通過反射機制調用目標類的代碼,動態將橫切邏輯和業務邏輯編制在一起。Proxy利用InvocationHandler動態創建一個符合某一接口的實例,生成目標類的代理對象。
InvocationHandler:API幫助文描述
英文描述:InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.
中文翻譯:每一個動態代理類都必須要實現InvocationHandler這個接口,並且每個代理類的實例都關聯到了一個handler,當我們通過代理對象調用一個方法的時候,這個方法的調用就會被轉發為由InvocationHandler這個接口的 invoke 方法來進行調用。
Object invoke(Object proxy,
Method method,
Object[] args)
throws Throwable
參數解釋:
proxy -指代所代理的那個真實對象
method –指代所要調用真實對象的某個方法的Method對象。
args –指代調用真實對象某個方法時接受的參數。
Proxy :解釋
使用其調用處理程序的指定值從子類(通常為動態代理類)構建新的 Proxy 實例
動態代理最重要方法:newProxyInstance
newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
返回一個指定接口的代理類實例,該接口可以將方法調用指派到指定的調用處理程序。
參數:
loader -一個ClassLoader對象,定義了由哪個ClassLoader對象來對生成的代理對象進行加載
interfaces -一個Interface對象的數組,表示的是將要給需要代理的對象提供一組什麼接口,如果提供了一組接口給它,那麼這個代理對象就宣稱實現了該接口(多態),這樣就能調用這組接口中的方法了
h -一個InvocationHandler對象,表示的是當這個動態代理對象在調用方法的時候,會關聯到哪一個InvocationHandler對象上
具體實現:代碼結構
定義業務邏輯接口:Subject
實現業務邏輯類:RealSubject
實現代理類:動態代理類就是實現 InvocationHandler 接口,增強方法都寫在這個類下面了。
客戶端調用:
運行結果:
代碼優化:客戶端每次都需要自己創建代理對象,我們將創建代理對象封裝到代理實現類當中。
客戶端代碼優化:
運行結果:
動態代理運用場景:
logging, tracing, profiling and monitoring 記錄跟蹤 優化 校準
Authentication 權限
Caching 緩存
Transactions 事務
感謝閱讀!!!給個關注 評論 轉發 行不行┭┮﹏┭┮
閱讀更多 少年編程 的文章