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

歡迎訪問 生活随笔!

生活随笔

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

java

Java学习之动态代理

發布時間:2025/3/21 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java学习之动态代理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java動態代理

為什么使用動態代理

當需要對某個類的某個方法進行修飾(增強)的時候,可以使用繼承、裝飾者模式和動態代理。

三種方式局限性:

  • 繼承:增強的對象不能改變,增強的內容不能改變。
  • 裝飾者模式:增強的對象不能改變,增強的內容能改變。
  • 動態代理:增強的對象可以改變,增強的內容可以改變。
  • 使用動態代理可以更加靈活地提高代碼的復用程度。

    舉個栗子:
    對于計算機教師這個類,有個teach()方法,時過境遷,舊的教學模式可能已經不適合高速發展的計算機行業了,因此在使用這個teach()方法可能需要前面或者后面要增加一點東西。但是對于老舊的項目,我們很難去理解前人的寫法和思維方式,因此不能輕易修改他們的代碼,所以我們可以使用代理去實現對teach()方法的增強(我這里分為前置增強和后置增強)。

    如何使用動態代理

    Object Proxy.newInstance(ClassLoader loader, Class[] interfaces, InvocationHandler ih)

  • loader:類加載器,將類加載到內存當中。
  • interfaces:代理對象要實現的接口。
  • ih:InvocationHandler,其中實現invoke()方法,來實現對目標對象的增強。
  • 返回值:jvm運行時動態生成的一個對象,它并不是我們的InvocationHandler類型,也不是我們定義的那組接口的類型,而是在運行是動態生成的一個對象
  • InvocationHandler接口

    該接口需要實現invoke()方法。

    Object invoke(Object proxy, Method method, Object[] args)

  • proxy:代理對象。
  • method:代理對象使用的目標方法。
  • args:目標方法的參數。
  • 返回值:method方法的返回值。
  • 在使用代理對象使用某個方法的時候,會調用生成代理對象時候傳入的InvocationHandler的invoke()方法,因此可以在這個invoke()里面寫需要增強的內容。

    Demo

    先給出兩個接口和一個實現類

    public interface Subject {public int outPut(int num); } public interface BSubject {public int outPut2(int num); } public class realSubject implements Subject, BSubject {@Overridepublic int outPut(int num) {System.out.println("outPut " + String.valueOf(num) + " people");return num;}@Overridepublic int outPut2(int num) {System.out.println("outPut2 " + String.valueOf(num) + " people");return num;} }

    使用動態代理

    前置增強接口:

    public interface BeforeAdvance { // 前置增強接口public void before(); }

    后置增強接口:

    public interface AfterAdvance { // 后置增強接口public void after(); }

    創建代理工廠,可以更加方便調用:

    import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;public class ProxyFactory {private Object targetObject; // 目標代理對象private BeforeAdvance beforeAdvance; // 前置增強private AfterAdvance afterAdvance; // 后置增強public Object createFactory() {ClassLoader loader = this.getClass().getClassLoader(); // 加載.class到內存Class[] interfaces = targetObject.getClass().getInterfaces(); // 得到realSubject所有接口(Waiter), 給代理對象提供了一組接口,這個代理對象就會實現這組接口,InvocationHandler ih = new InvocationHandler() {@Override// proxy 是代理對象,是在jvm運行時動態生成的一個對象,它并不是我們的InvocationHandler類型,也不是我們定義的那組接口的類型,而是在運行是動態生成的一個對象// Method 是目標對象需要增強的方法// args是實參public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if(beforeAdvance != null) { // 調用前置增強方法beforeAdvance.before();}Object result = method.invoke(targetObject, args); // 通過反射調用目標代理對象的目標方法, result是目標方法的返回值if(afterAdvance != null) { // 調用后置增強方法afterAdvance.after();}return result;}};return Proxy.newProxyInstance(loader, interfaces, ih); // 得到一個代理對象}public AfterAdvance getAfterAdvance() {return afterAdvance;}public void setAfterAdvance(AfterAdvance afterAdvance) {this.afterAdvance = afterAdvance;}public BeforeAdvance getBeforeAdvance() {return beforeAdvance;}public void setBeforeAdvance(BeforeAdvance beforeAdvance) {this.beforeAdvance = beforeAdvance;}public Object getTargetObject() {return targetObject;}public void setTargetObject(Object targetObject) {this.targetObject = targetObject;} }

    示例:

    import org.junit.Test;public class Demo {@Testpublic void fun() {ProxyFactory proxyfactory = new ProxyFactory();// 代理的目標對象proxyfactory.setTargetObject(new realSubject());// 前置增強接口實現proxyfactory.setBeforeAdvance(new BeforeAdvance() {@Overridepublic void before() {System.out.println("hello");}});// 后置增強接口實現proxyfactory.setAfterAdvance(new AfterAdvance() {@Overridepublic void after() {System.out.println("byebye");}});// 生成對Subject接口的實現類對象Subject subject = (Subject) proxyfactory.createFactory(); // 通過newInstance()得到一個代理對象,這個代理對象實現了Subject接口,因此可以強轉為Subject接口類。BSubject subject2 = (BSubject) proxyfactory.createFactory();Object result = subject.outPut(100); // 對應InvocationHandler的invoke方法:subject為proxy, outPut為method, 參數為argsSystem.out.println(result);System.out.println("-----");Object result2 = subject2.outPut2(50);System.out.println(result2);} }輸出: hello outPut 100 people byebye 100 ----- hello outPut2 50 people byebye 50

    在這里面,只要使用反射,method.invoke()就可以調用代理的目標對象的該方法,然后實現前置增強BeforeAdvance接口和后置增強AfterAdvance接口,就可以實現對方法內容的增強了。
    其中不同接口的不同實現方法都可以重用BeforeAdvance和AfterAdvance。
    對于不同的增強對象也可以使用,只要targetObject改一下就可以了。

    附上一篇講的不錯的文章

    轉載于:https://www.cnblogs.com/fightfordream/p/7965479.html

    總結

    以上是生活随笔為你收集整理的Java学习之动态代理的全部內容,希望文章能夠幫你解決所遇到的問題。

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