国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

java jdk動態代理詳解

2019-11-26 15:58:30
字體:
來源:轉載
供稿:網友

jdk動態代理要對一個類進行代理,被代理的類必須實現至少一個接口,并且只有接口中的方法才能被代理。

jdk實現動態代理一般分為三步:

1. 編寫接口和實現類。

2. 寫一個處理器,該處理器實現InvocationHandler接口,該接口只有一個方法,其簽名為public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;可在該處理器的實現方法中,在方法調用前和調用后加入自己的代碼,從而進行動態攔截。要注意的是proxy為生成的動態代理類,并不是真的我們被代理的類,所以可在處理器中加入Object類型的成員變量,指向我們真正要求被代理的類(即第1步中的實現類)。

3. 使用java.lang.reflect.Proxy類的newProxyInstance方法生成動態代理類。對所有要代理方法的調用,都是直接調用生成的動態代理類的方法即可,但是要先對它進行強制類型轉換,轉換成我們要調用的方法的接口。

JDK原理分析:
通過分析Proxy的源代碼,可看到動態代理類的詳細生成。newProxyInstance方法首先生成動態代理類的Class實例,再調用它的參數類型為InvocationHandler的構造函數來生成動態代理類并返回。

動態代理類的Class實例是怎么生成的呢,是通過ProxyGenerator類來生成動態代理類的class字節流,把它載入方法區。

分析class字節流生成的過程可以看到它使用Proxy為它的父類,實現所有要代理的接口的方法,每個方法的實現體里主要都是調用處理器的invoke方法。

class字節流的生成過程的主要代碼如下:

復制代碼 代碼如下:

private byte[] generateClassFile()
    {
        addProxyMethod(hashCodeMethod, java/lang/Object);
        addProxyMethod(equalsMethod, java/lang/Object);
        addProxyMethod(toStringMethod, java/lang/Object);
        for(int i = 0; i < interfaces.length; i++)
        {
            Method amethod[] = interfaces[i].getMethods();
            for(int k = 0; k < amethod.length; k++)
                addProxyMethod(amethod[k], interfaces[i]);

        }

        List list;
        for(Iterator iterator = proxyMethods.values().iterator(); iterator.hasNext(); checkReturnTypes(list))
            list = (List)iterator.next();

        try
        {
            methods.add(generateConstructor());
            for(Iterator iterator1 = proxyMethods.values().iterator(); iterator1.hasNext();)
            {
                List list1 = (List)iterator1.next();
                Iterator iterator2 = list1.iterator();
                while(iterator2.hasNext())
                {
                    ProxyMethod proxymethod = (ProxyMethod)iterator2.next();
                    fields.add(new FieldInfo(proxymethod.methodFieldName, "Ljava/lang/reflect/Method;", 10));
                    methods.add(<SPAN style="COLOR: red">proxymethod.generateMethod()</SPAN><SPAN style="COLOR: #000000">);</SPAN>       


復制代碼 代碼如下:

        } 
    } 

    methods.add(generateStaticInitializer()); 

catch(IOException ioexception) 

    throw new InternalError("unexpected I/O Exception"); 

if(methods.size() > 65535) 
    throw new IllegalArgumentException("method limit exceeded"); 
if(fields.size() > 65535) 
    throw new IllegalArgumentException("field limit exceeded"); 
cp.getClass(dotToSlash(className)); 
cp.getClass("java/lang/reflect/Proxy"); 
for(int j = 0; j < interfaces.length; j++) 
    cp.getClass(dotToSlash(interfaces[j].getName())); 

cp.setReadOnly(); 
ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(); 
DataOutputStream dataoutputstream = new DataOutputStream(bytearrayoutputstream); 
try 

    dataoutputstream.writeInt(-889275714); 
    dataoutputstream.writeShort(0); 
    dataoutputstream.writeShort(49); 
    cp.write(dataoutputstream); 
    dataoutputstream.writeShort(49); 
    dataoutputstream.writeShort(cp.getClass(dotToSlash(className))); 
    dataoutputstream.writeShort(cp.getClass("java/lang/reflect/Proxy")); 
    dataoutputstream.writeShort(interfaces.length); 
    for(int l = 0; l < interfaces.length; l++) 
        dataoutputstream.writeShort(cp.getClass(dotToSlash(interfaces[l].getName()))); 

    dataoutputstream.writeShort(fields.size()); 
    FieldInfo fieldinfo; 

復制代碼 代碼如下:

//添加屬性
for(Iterator iterator3 = fields.iterator(); iterator3.hasNext(); fieldinfo.write(dataoutputstream))

fieldinfo = (FieldInfo)iterator3.next();
            //添加方法
            dataoutputstream.writeShort(methods.size());
            MethodInfo methodinfo;
            for(Iterator iterator4 = methods.iterator(); iterator4.hasNext(); methodinfo.write(dataoutputstream))
                methodinfo = (MethodInfo)iterator4.next();

            dataoutputstream.writeShort(0);
        }
        catch(IOException ioexception1)
        {
            throw new InternalError("unexpected I/O Exception");
        }
        return bytearrayoutputstream.toByteArray();
    }


注:代碼中加紅部分proxymethod.generateMethod()為每個方法生成方法體,通過查看源碼可以看出都是在調用InvocationHandler接口的實現處理器的invoke方法。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 维西| 华坪县| 赤峰市| 奎屯市| 司法| 武平县| 沂南县| 无锡市| 梁河县| 阿鲁科尔沁旗| 浦东新区| 遵义市| 榆树市| 景泰县| 饶平县| 璧山县| 澄江县| 临夏市| 太保市| 柯坪县| 东山县| 浙江省| 南涧| 乐安县| 梅河口市| 新兴县| 翼城县| 沾益县| 绍兴县| 信宜市| 临夏市| 金堂县| 成安县| 松滋市| 吴忠市| 安顺市| 庐江县| SHOW| 鹤壁市| 沙湾县| 乌拉特中旗|