java jdk動態代理模式舉例淺析


代理模式概述

代理模式是為了提供額外或不同的操作,而插入的用來替代”實際”對象的對象,這些操作涉及到與”實際”對象的通信,因此代理通常充當中間人角色。

java中常用的動態代理模式為jdk動態代理和cglib動態代理。

 

反射技術

了解動態代理之前,需要先了解一下java中的反射,反射在框架中的應用非常廣泛,它能夠配置:類的全限定名,方法和參數。在運行時,動態的完成類的初始化,或者反射調用某些方法。

我們可以通過Class.forName()方法加載類,並用getConstructor方法配置參數。例:

object = (goodsServiceImpl)=Class.forName("com.xjx.test.goodsServiceImpl").getConstructor(String.class).newInstance("計算機");

 

1. jdk動態代理舉例

jdk動態代理由java.lang.reflect.*包提供,它必須借助一個接口才能實現代理。

我們舉個例子來實現jdk動態代理並簡要分析:

首先我們定義一個接口:

public interface jdkProxy { public void test(String tString); }

以及它的實現類:

public class jdkProxyImpl implements jdkProxy{ @Override public void test(String tString) { // TODO Auto-generated method stub
        System.out.println("代理內方法"+tString); } }

接下來我們要進行代理。代理過程分2步:

1.建立起代理對象和真實服務對象之間的關系,生產代理對象;

2.實現邏輯的代理;

在jdk動態代理中,要實現代理邏輯就必須實現InvocationHandler接口。它里面定義了一個invoke方法,每當我們通過代理對象調用方法時,它都會被轉發到這個invoke方法,我們來

定義一個實現代理邏輯的類:

public class jdkProxyExample implements InvocationHandler{ //真實對象
    private Object target = null; /** * 建立真實對象和代理對象的代理關系 * @param target真實對象 * @return 代理對象 */
    public Object setTargetAndBind(Object target) { this.target = target; /** * 參數1:getClassLoader()提供類加載器;
      參數2:getInterfaces()要掛載動態代理對象的接口,就是target的接口;
*/ return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), this); } /** * 代理方法邏輯 * @param:代理對象 * method:當前調度方法 * args:當前方法參數 * return 代理結果返回 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("進入代理對象方法,在此執行代理對象之前的一些操作"); //執行目標對象中的某個方法 Object object = method.invoke(target, args); System.out.println("調用代理對象方法之后的操作"); return object; } }
1.1 生成一個代理對象

setTargetAndBind()這個方法內的newProxyInstance()方法通過傳入被代理內,再通過反射,生成一個代理類。

1.2 實現代理類的邏輯方法

object obj = method.invoke(target,args),這個方法相當於調度真實對象的方法,只不過是通過反射區實現。它返回方法的執行結果。

並且在invoke方法里,可以在調用真實對象方法之前和之后做一些其他的操作,這也是AOP的實現原理

 

這樣,一個jdk動態代理就完成了,接下來可以寫個測試類測試一下:

 

public class jdkProxyExampleTest {

    @Test
    public void testProxy() {
        jdkProxyExample jdkProxyExample = new jdkProxyExample();
        //綁定關系,此時jdkProxy已經是一個代理對象
        jdkProxy jdkProxy = (jdkProxy)jdkProxyExample.setTargetAndBind(new jdkProxyImpl());
        //執行代理對象方法
        jdkProxy.test("動態代理jdk");
    }
}

 

打印結果如下:

 

2. 為什么jdk動態代理一定需要目標對象實現接口?(可能有誤

1.我們可以看到,在綁定關系的方法中,實現被代理類的反射,需要我們提供接口,然后它通過接口實現代理類。沒有它就找不到反射的方法。

2.由於java的單繼承機制:首先jdk動態代理是通過newInstance動態的生成代理對象的,newInstance通過ProxyGenerator生成的字節碼代表的類繼承了Proxy類:

public final class $Proxy0 extends Proxy
  implements jdkProxy{
    ...
}
$Proxy0這個類通過反編譯獲得,它就是jdkProxy的實現類的動態的代理類。
由於java的單繼承機制,被代理對象不能再被其他的類繼承,那么我們如果想建立代理類和被代理類之間的關系,只能通過實現同一個接口了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM