欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java jdk動(dòng)態(tài)代理詳解

 更新時(shí)間:2013年09月11日 08:55:48   作者:  
動(dòng)態(tài)代理類(lèi)的Class實(shí)例是怎么生成的呢,是通過(guò)ProxyGenerator類(lèi)來(lái)生成動(dòng)態(tài)代理類(lèi)的class字節(jié)流,把它載入方法區(qū)

jdk動(dòng)態(tài)代理要對(duì)一個(gè)類(lèi)進(jìn)行代理,被代理的類(lèi)必須實(shí)現(xiàn)至少一個(gè)接口,并且只有接口中的方法才能被代理。

jdk實(shí)現(xiàn)動(dòng)態(tài)代理一般分為三步:

1. 編寫(xiě)接口和實(shí)現(xiàn)類(lèi)。

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

3. 使用java.lang.reflect.Proxy類(lèi)的newProxyInstance方法生成動(dòng)態(tài)代理類(lèi)。對(duì)所有要代理方法的調(diào)用,都是直接調(diào)用生成的動(dòng)態(tài)代理類(lèi)的方法即可,但是要先對(duì)它進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換,轉(zhuǎn)換成我們要調(diào)用的方法的接口。

JDK原理分析:
通過(guò)分析Proxy的源代碼,可看到動(dòng)態(tài)代理類(lèi)的詳細(xì)生成。newProxyInstance方法首先生成動(dòng)態(tài)代理類(lèi)的Class實(shí)例,再調(diào)用它的參數(shù)類(lèi)型為InvocationHandler的構(gòu)造函數(shù)來(lái)生成動(dòng)態(tài)代理類(lèi)并返回。

動(dòng)態(tài)代理類(lèi)的Class實(shí)例是怎么生成的呢,是通過(guò)ProxyGenerator類(lèi)來(lái)生成動(dòng)態(tài)代理類(lèi)的class字節(jié)流,把它載入方法區(qū)。

分析class字節(jié)流生成的過(guò)程可以看到它使用Proxy為它的父類(lèi),實(shí)現(xiàn)所有要代理的接口的方法,每個(gè)方法的實(shí)現(xiàn)體里主要都是調(diào)用處理器的invoke方法。

class字節(jié)流的生成過(guò)程的主要代碼如下:

復(fù)制代碼 代碼如下:

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>       


復(fù)制代碼 代碼如下:

        } 
    } 

    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; 

復(fù)制代碼 代碼如下:

//添加屬性
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()為每個(gè)方法生成方法體,通過(guò)查看源碼可以看出都是在調(diào)用InvocationHandler接口的實(shí)現(xiàn)處理器的invoke方法。

相關(guān)文章

  • java多線程實(shí)現(xiàn)文件下載

    java多線程實(shí)現(xiàn)文件下載

    這篇文章主要為大家詳細(xì)介紹了java多線程實(shí)現(xiàn)文件下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • mybatis集成到spring的方式詳解

    mybatis集成到spring的方式詳解

    這篇文章主要介紹了mybatis是如何集成到spring的,將mybatis集成到spring之后,就可以被spring的ioc容器托管,再也不用自己創(chuàng)建SqlSessionFactory?、打開(kāi)SqlSession等操作,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • 詳解AOP與Filter攔截請(qǐng)求打印日志實(shí)用例子

    詳解AOP與Filter攔截請(qǐng)求打印日志實(shí)用例子

    這篇文章主要介紹了詳解AOP與Filter攔截請(qǐng)求打印日志實(shí)用例子,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • JDBC實(shí)現(xiàn)數(shù)據(jù)庫(kù)增刪改查功能

    JDBC實(shí)現(xiàn)數(shù)據(jù)庫(kù)增刪改查功能

    這篇文章主要為大家詳細(xì)介紹了JDBC實(shí)現(xiàn)數(shù)據(jù)庫(kù)增刪改查功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • Java詳解IO流創(chuàng)建讀取與寫(xiě)入操作

    Java詳解IO流創(chuàng)建讀取與寫(xiě)入操作

    這篇文章主要介紹了Java IO流,同時(shí)也介紹了流中的一些相關(guān)的內(nèi)容,并且通過(guò)大量的案例供大家理解。最后通過(guò)一些經(jīng)典的案例幫助大家對(duì)前面所學(xué)的知識(shí)做了一個(gè)綜合的應(yīng)用,需要的朋友可以參考一下
    2022-05-05
  • Spring自動(dòng)裝配與掃描注解代碼詳解

    Spring自動(dòng)裝配與掃描注解代碼詳解

    這篇文章主要介紹了Spring自動(dòng)裝配與掃描注解代碼詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • 用Spring Native將SpringBoot程序轉(zhuǎn)換為GraalVM

    用Spring Native將SpringBoot程序轉(zhuǎn)換為GraalVM

    這篇文章主要介紹了用Spring Native將SpringBoot程序轉(zhuǎn)換為GraalVM的方法,幫助大家更好的理解和學(xué)習(xí)使用SpringBoot,感興趣的朋友可以了解下
    2021-04-04
  • Java?spring注解@PostConstruct實(shí)戰(zhàn)案例講解

    Java?spring注解@PostConstruct實(shí)戰(zhàn)案例講解

    我們?cè)赟pring項(xiàng)目中經(jīng)常會(huì)遇到@PostConstruct注解,可能有的伙伴對(duì)這個(gè)注解很陌生,下面這篇文章主要給大家介紹了關(guān)于Java?spring注解@PostConstruct實(shí)戰(zhàn)案例講解的相關(guān)資料,需要的朋友可以參考下
    2023-12-12
  • 淺談java object對(duì)象在heap中的結(jié)構(gòu)

    淺談java object對(duì)象在heap中的結(jié)構(gòu)

    本文主要介紹了淺談java object對(duì)象在heap中的結(jié)構(gòu),感興趣的同學(xué),可以參考下。
    2021-06-06
  • SpringBoot2 整合 ClickHouse數(shù)據(jù)庫(kù)案例解析

    SpringBoot2 整合 ClickHouse數(shù)據(jù)庫(kù)案例解析

    這篇文章主要介紹了SpringBoot2 整合 ClickHouse數(shù)據(jù)庫(kù)案例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10

最新評(píng)論