国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 深入解析java中的靜態(tài)代理與動態(tài)代理

深入解析java中的靜態(tài)代理與動態(tài)代理

2019-10-16 10:19java教程網(wǎng) Java教程

本篇文章是對java中的靜態(tài)代理與動態(tài)代理進行了詳細的分析介紹,需要的朋友可以過來參考下,希望對大家有所幫助

java編碼中經(jīng)常用到代理,代理分為靜態(tài)代理和動態(tài)代理。其中動態(tài)代理可以實現(xiàn)spring中的aop。

一、靜態(tài)代理:程序運行之前,程序員就要編寫proxy,然后進行編譯,即在程序運行之前,代理類的字節(jié)碼文件就已經(jīng)生成了

被代理類的公共父類

復制代碼代碼如下:

package staticproxy;
public abstract class BaseClass {
    public abstract void add();
}


被代理類

復制代碼代碼如下:

package staticproxy;
public class A extends BaseClass {
    public void add() {
        System.out.println("A add !");
    }
}


代理類

復制代碼代碼如下:

package staticproxy;
public class Proxy {
    BaseClass baseClass;
    public void add() {
        baseClass.add();
    }
    public void setBaseClass(BaseClass baseClass) {
        this.baseClass = baseClass;
    }
    public static void main(String[] args) {
        BaseClass baseClass = new A();
        Proxy proxy = new Proxy();
        proxy.setBaseClass(baseClass);
        proxy.add();
    }
}


二、動態(tài)代理:實際的代碼在編譯期間并沒有生成,而是在運行期間運用反射機制動態(tài)的生成

 

被代理類接口

復制代碼代碼如下:

package jdkproxy;
public interface Service {
    public void add();
    public void update();
}


被代理類A

復制代碼代碼如下:

package jdkproxy;
public class AService implements Service {
    public void add() {
        System.out.println("AService add>>>>>>>>>>>>>>>>>>");
    }
    public void update() {
        System.out.println("AService update>>>>>>>>>>>>>>>");
    }
}


被代理類B

復制代碼代碼如下:

package jdkproxy;
public class BService implements Service {
    public void add() {
        System.out.println("BService add---------------");
    }
    public void update() {
        System.out.println("BService update---------------");
    }
}


代理類

復制代碼代碼如下:

package jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    MyInvocationHandler() {
        super();
    }
    MyInvocationHandler(Object target) {
        super();
        this.target = target;
    }
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // 程序執(zhí)行前加入邏輯
        System.out.println("before-----------------------------");
        // 程序執(zhí)行
        Object result = method.invoke(target, args);
        //程序執(zhí)行后加入邏輯
        System.out.println("after------------------------------");
        return result;
    }
    public Object getTarget() {
        return target;
    }
    public void setTarget(Object target) {
        this.target = target;
    }
}


測試類

復制代碼代碼如下:

package jdkproxy;
import java.lang.reflect.Proxy;
public class Test {
    public static void main(String[] args) {
        Service aService = new AService();
        MyInvocationHandler handler = new MyInvocationHandler(aService);
        // Proxy為InvocationHandler實現(xiàn)類動態(tài)創(chuàng)建一個符合某一接口的代理實例
        Service aServiceProxy = (Service) Proxy.newProxyInstance(aService
                .getClass().getClassLoader(), aService.getClass()
                .getInterfaces(), handler);

        //由動態(tài)生成的代理對象來aServiceProxy 代理執(zhí)行程序,其中aServiceProxy 符合Service接口
        aServiceProxy.add();
        System.out.println();
        aServiceProxy.update();
        // 以下是對B的代理
        // Service bService = new BService();
        // MyInvocationHandler handler = new MyInvocationHandler(bService);
        // Service bServiceProxy = (Service) Proxy.newProxyInstance(bService
        // .getClass().getClassLoader(), bService.getClass()
        // .getInterfaces(), handler);
        // bServiceProxy.add();
        // System.out.println();
        // bServiceProxy.update();
    }
}


輸出結(jié)果:
before-----------------------------
AService add>>>>>>>>>>>>>>>>>>
after------------------------------
before-----------------------------
AService update>>>>>>>>>>>>>>>
after------------------------------

 

其中上述標紅的語句是產(chǎn)生代理類的關(guān)鍵代碼,可以產(chǎn)生一個符合Service接口的代理對象,newProxyInstance這個方法會做這樣一件事情,他將把你要代理的全部接口,用一個由代碼動態(tài)生成的類來實現(xiàn),該類中所有的接口中的方法都重寫為調(diào)用InvocationHandler.invoke()方法。

下面詳細介紹是如何實現(xiàn)代理對象的生成的

Proxy的newProxyInstance方法,其中,為了看起來方便,已經(jīng)將該方法中的異常處理語句刪減

下下面public static Object newProxyInstance(ClassLoader loader,  Class<?>[] interfaces,InvocationHandler h) throws 

復制代碼代碼如下:

    public static Object newProxyInstance(ClassLoader loader,  Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException  
    {  
        if (h == null) {  
            throw new NullPointerException();  
        }  
        //生成指定的代理類
        Class cl = getProxyClass(loader, interfaces);  
        Constructor cons = cl.getConstructor(constructorParams);  
        // 生成代理類的實例,并把MyInvocationHandler的實例傳給它的構(gòu)造方法,代理類對象實際執(zhí)行都會調(diào)用MyInvocationHandler的invoke方法,所以代理類對象中維持一個MyInvocationHandler引用  
        return (Object) cons.newInstance(new Object[] { h });  
    }  其中g(shù)etProxyClass方法返回代理類的實例


Proxy的getProxyClass方法

復制代碼代碼如下:

public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException
{
    //前面省略很多緩存、異常處理、判斷邏輯代碼,為了使程序更加突出
    byte[] proxyClassFile =    ProxyGenerator.generateProxyClass(proxyName, interfaces);
    proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
    proxyClasses.put(proxyClass, null);
    return proxyClass;
}


下面看ProxyGenerator的generateProxyClass方法,該方法最終產(chǎn)生代理類的字節(jié)碼文件:

復制代碼代碼如下:

public static byte[] generateProxyClass(final String name, Class[] interfaces)  
   {  
       ProxyGenerator gen = new ProxyGenerator(name, interfaces);  
    // 這里動態(tài)生成代理類的字節(jié)碼
       final byte[] classFile = gen.generateClassFile();  
    // 如果saveGeneratedFiles的值為true,則會把所生成的代理類的字節(jié)碼保存到硬盤上  
       if (saveGeneratedFiles) {  
           java.security.AccessController.doPrivileged(  
           new java.security.PrivilegedAction<Void>() {  
               public Void run() {  
                   try {  
                       FileOutputStream file =  
                           new FileOutputStream(dotToSlash(name) + ".class");  
                       file.write(classFile);  
                       file.close();  
                       return null;  
                   } catch (IOException e) {  
                       throw new InternalError(  
                           "I/O exception saving generated file: " + e);  
                   }  
               }  
           });  
       }  
    // 返回代理類的字節(jié)碼  
       return classFile;  
   }


那么最終生成的代理類到底是什么樣子呢,如下(省略了一下equals,hashcode,toString等方法,只展示構(gòu)造函數(shù)和add方法):

復制代碼代碼如下:

public final class $Proxy11 extends Proxy implements Service  
{      // 構(gòu)造方法,參數(shù)就是剛才傳過來的MyInvocationHandler類的實例  
    public $Proxy11(InvocationHandler invocationhandler)  
    {  
        super(invocationhandler);  
    }  

    /** 
     * 繼承的add方法,重寫,調(diào)用MyInvocationHandler中的invoke方法
     */  
    public final void add()  
    {  
        try  
        {  
            // 實際上就是調(diào)用MyInvocationHandler中的invoke方法  
            super.h.invoke(this, m3, null);  
            return;  
        }  
        catch(Error _ex) { }  
       catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
   }  
}  
 

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 成人a在线视频免费观看 | 国产区在线观看 | 亚洲欧美另类久久久精品2019 | 国产成人精品a视频一区www | 中文字幕高清一区 | 精品在线一区 | 日韩欧美视频 | 91精品国产综合久久久久久漫画 | 国产毛片久久久久 | 国产精品毛片一区视频播不卡 | 毛片一级在线 | 亚洲va中文字幕 | 久久精品国产亚洲 | 亚洲情av| 日韩电影一区二区三区 | 成人看片免费 | 日本久久精品 | 国产精彩视频 | 成人羞羞网站 | 成人免费观看49www在线观看 | 日韩一区精品 | 亚洲精品国产一区 | 四季久久免费一区二区三区四区 | hsck成人网| 一区二区日本 | www.av在线| 日狠狠 | 亚洲精品久久久久久下一站 | 久久久久久久97 | 亚洲视频免费观看 | 成人中文字幕在线观看 | 国产精品3区 | 成人免费视频播放 | 日韩成人在线播放 | 亚洲电影在线观看 | 久久激情久久 | 人妖天堂狠狠ts人妖天堂狠狠 | 羞羞视频免费观看 | 最好的2019中文大全在线观看 | 九九天堂 | 日韩在线视频观看 |