最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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程序窗口在屏幕中間顯示

    如何把Java程序窗口在屏幕中間顯示

    大家在日常Java開(kāi)發(fā)中,可能會(huì)需要把程序窗口定位在屏幕中間,那該如何操作呢,下面來(lái)一起看看。
    2016-08-08
  • Java?Scanner?類(lèi)讀取一維數(shù)組二維數(shù)組示例詳解

    Java?Scanner?類(lèi)讀取一維數(shù)組二維數(shù)組示例詳解

    這篇文章主要為大家介紹了Java?Scanner?類(lèi)讀取一維數(shù)組二維數(shù)組示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • 如何利用Spring把元素解析成BeanDefinition對(duì)象

    如何利用Spring把元素解析成BeanDefinition對(duì)象

    這篇文章主要介紹了如何利用Spring把元素解析成BeanDefinition對(duì)象,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • Java如何通過(guò)反射獲取Constructor、Field、Method對(duì)象

    Java如何通過(guò)反射獲取Constructor、Field、Method對(duì)象

    反射指的是對(duì)象的反向處理操作,根據(jù)對(duì)象取得對(duì)象的來(lái)源信息,在反射的世界里面,看重的不再是一個(gè)對(duì)象,而是對(duì)象身后的組成,下面這篇文章主要給大家介紹了關(guān)于Java如何通過(guò)反射獲取Constructor、Field、Method對(duì)象的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • springboot整合日志處理Logback的實(shí)現(xiàn)示例

    springboot整合日志處理Logback的實(shí)現(xiàn)示例

    Logback是由log4j創(chuàng)始人設(shè)計(jì)的又一個(gè)開(kāi)源日志組件,本文主要介紹了springboot整合日志處理Logback,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01
  • SpringBoot接口防抖(防重復(fù)提交)的實(shí)現(xiàn)方案

    SpringBoot接口防抖(防重復(fù)提交)的實(shí)現(xiàn)方案

    所謂防抖,一是防用戶手抖,二是防網(wǎng)絡(luò)抖動(dòng),在Web系統(tǒng)中,表單提交是一個(gè)非常常見(jiàn)的功能,如果不加控制,容易因?yàn)橛脩舻恼`操作或網(wǎng)絡(luò)延遲導(dǎo)致同一請(qǐng)求被發(fā)送多次,所以本文給大家介紹了SpringBoot接口防抖(防重復(fù)提交)的實(shí)現(xiàn)方案,需要的朋友可以參考下
    2024-04-04
  • java中DateUtils時(shí)間工具類(lèi)詳解

    java中DateUtils時(shí)間工具類(lèi)詳解

    這篇文章主要為大家詳細(xì)介紹了java中DateUtils時(shí)間工具類(lèi),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • spring/springboot整合dubbo詳細(xì)教程

    spring/springboot整合dubbo詳細(xì)教程

    今天教大家如何使用spring/springboot整合dubbo,文中有非常詳細(xì)的圖文介紹及代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • Java的Jackson庫(kù)中復(fù)雜對(duì)象集合的幾種簡(jiǎn)單轉(zhuǎn)換

    Java的Jackson庫(kù)中復(fù)雜對(duì)象集合的幾種簡(jiǎn)單轉(zhuǎn)換

    本文主要介紹了Java的Jackson庫(kù)中復(fù)雜對(duì)象集合的幾種簡(jiǎn)單轉(zhuǎn)換。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • Java?@Scheduled定時(shí)器用法解析

    Java?@Scheduled定時(shí)器用法解析

    這篇文章主要介紹了Java?@Scheduled定時(shí)器用法解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05

最新評(píng)論

泗水县| 于田县| 连江县| 曲水县| 汉寿县| 绍兴市| 靖江市| 精河县| 临泽县| 姚安县| 修文县| 南汇区| 灵丘县| 习水县| 禄丰县| 白河县| 凉城县| 柞水县| 长垣县| 五大连池市| 三穗县| 怀来县| 昭觉县| 绥棱县| 安图县| 中超| 诸暨市| 探索| 裕民县| 县级市| 磐石市| 巴南区| 清水河县| 永兴县| 上虞市| 延边| 彭水| 江油市| 湛江市| 宁武县| 商南县|