日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

[Java5新特性]动态代理

發布時間:2024/6/18 java 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Java5新特性]动态代理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

動態代理概述

代理模式是Java設計模式中的一種,其特征為代理類與委托類有同樣的接口,代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事后處理消息等。代理類與委托類之間通常存在關聯關系,一個代理類的對象與一個委托類的對象關聯,代理類的對象本身并不真正實現業務,而是通過調用委托類對象的相關方法來提供具體業務。

在Java中的java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler接口,通過這個類和接口可以生成JDK動態代理或動態代理對象。

按照代理的創建時間不同,可以分為兩種:

  • 靜態代理:手動創建,再對其編譯。在程序運行前,代理類的.class文件就已經存在。
  • 動態代理:在程序運行時,通過反射機制動態創建而成。

動態代理原理

動態代理的實現原理有些類似于過濾器的實現原理,但有所不同。動態代理的代理類與委托類之間的關系更像是明星與經紀人之間的關系,也就是說,如果你想找某個明星演出的話,并不是找他本人,而是找到他的經紀人就可以了。動態代理的實現過程很類似于這個過程,具體請看下圖:

Proxy代理類

Proxy類是Java的java.lang.reflect包下提供的,該類用于創建動態代理類和代理對象的靜態方法,它也是所有動態代理類的父類。如果在程序中為一個或多個接口動態地生成實現類,就可以用Proxy類來創建動態代理類;如果需要為一個或多個接口動態地創建實例,也可以使用Proxy類來創建動態代理實例。

方法摘要
static InvocationHandlergetInvocationHandler(Object proxy)
static Class<?>getProxyClass(ClassLoader loader, Class<?>… interfaces)
static booleanisProxyClass(Class<?> cl)
static ObjectnewProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
  • static Class<?> getProxyClass(ClassLoader loader, Class<?>… interfaces):創建一個動態代理類所對應的Class對象,該代理類將實現interfaces所指定的多個接口。第一個ClassLoader參數指定生成動態代理類的類加載器。
  • static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h):直接創建一個動態代理對象,該代理對象的實現類實現了interfaces指定的系列接口,執行代理對象的每個方法時都會被替換執行InvocationHandler對象的invoke()方法。

InvocationHandler

InvocationHandler接口提供了invoke()方法,用于替換代理對象的每一個方法。真實業務類可以通過代理類對象調用InvocationHandler接口提供的invoke()方法,來替代調用委托類的真實方法。

以下是InvocationHandler的API內容:

方法摘要
Objectinvoke(Object proxy, Method method, Object[] args)

Object invoke(Object proxy, Method method, Object[] args):在代理實例上處理方法調用并返回結果。在與方法關聯的代理實例上調用方法時,將在調用處理程序上調用此方法。

  • 參數proxy:表示代理類對象,也就是Proxy.newProxyInstance()方法返回的對象,通常用不上。
  • 參數method:表示當前被調用方法的反射對象。
  • 參數args:表示調用目標方法時傳入的實參。

實現動態代理

利用Java提供的Proxy類和InvocationHandler接口來生成動態代理類或動態代理對象,具體實現步驟如下:

  • 定義一個業務接口,該接口提供具體業務方法的定義。
public interface Person {void sayMe();void sayHello(String name); }
  • 定義一個InvocationHandler接口的實現類,并重寫invoke()方法。
public class MyInvocationHandler implements InvocationHandler {/*** 執行動態代理對象的所有方法時,都會被替換成執行下面的invoke()方法.* * 參數proxy:代表動態代理對象.* * 參數method:代表正在執行的方法.* * 參數args:代表調用目標方法時傳入的實參.*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println("---正在執行的方法: "+method);if(args == null){System.out.println("當前調用的方法沒有參數.");}else{System.out.println("當前調用的方法需要傳入的實參為:");for (Object val : args) {System.out.println(val);}}return null;} }
  • 編寫一個用于測試動態代理的測試類。
public class ProxyTest {public static void main(String[] args) {// 創建一個InvocationHandler對象InvocationHandler handler = new MyInvocationHandler();// 通過Proxy類使用指定的InvocationHandler來生成動態代理對象Person p = (Person)Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, handler);// 調用動態代理對象的業務方法p.sayMe();p.sayHello("張無忌");} }

動態代理的作用

通過Java提供的Proxy類和InvocationHandler接口生成的動態代理類,可以阻止調用委托類的方法、過濾參數及修改對應方法的返回值等作用。實現業務接口方法的實現類即委托類,具體操作如下:

  • 創建一個實現類,實現Person接口,并重寫業務方法。
public class Fanbingbing implements Person {@Overridepublic void sayMe() {System.out.println("我真的是范冰冰哦!");}@Overridepublic String sayHello(String name) {System.out.println("你好:"+name+",我等你很久了...");return "我終于見到范冰冰啦!";} }
  • 編寫一個用于測試動態代理的測試類。
public class FanbingbingTest {public static void main(String[] args) {Person p = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(),Fanbingbing.class.getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method,Object[] args) throws Throwable {// 通過method的getName()方法獲取業務方法名,進行阻止.if (method.getName().equals("sayMe")) {System.out.println("你想多了,哪那么容易見到啊!");return null;}// 通過args獲取實參,進行修改if(method.getName().equals("sayHello")){String name = (String)args[0];method.invoke(Class.forName("app.java.proxy.Fanbingbing").newInstance(), "某局長");}// 修改返回值if(method.getName().equals("sayHello")){return "都是假的!";}return null;}});p.sayMe();p.sayHello("張無忌");} }

轉載說明:請注明作者及原文鏈接,謝謝!

轉載于:https://www.cnblogs.com/longestory/p/4566981.html

總結

以上是生活随笔為你收集整理的[Java5新特性]动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。