亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中的代理是指什么

發布時間:2020-06-28 14:55:33 來源:億速云 閱讀:133 作者:元一 欄目:編程語言

本篇文章給大家分享的是有關java中的代理,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

代理模式在設計模式中的定義就是:為其他對象提供一種代理以控制對這個對象的訪問。說白了就是,在一些情況下客戶不想或者不能直接引用一個對象,而代理對象可以在客戶和目標對象之間起到中介作用,去掉客戶不能看到的內容和服務或者增添客戶需要的額外服務。

java中的代理是指什么

Java的靜態代理

舉個例子,如果我們一些水果,比如:香蕉、蘋果等,寫成Java代碼,大概是下面這個樣子:

//Fruit.java/**
 * 水果的接口
 */public interface Fruit {    /**
     * 獲取水果的名字
     */
    public String getName();
}//Apple.javapublic class Apple implements Fruit {    @Override
    public String getName() {        return "蘋果";
    }
}//Banana.javapublic class Banana implements Fruit {    @Override
    public String getName() {        return "香蕉";
    }
}

吃水果,你要削皮吧,你不能每個水果都寫一個子類,類處理削皮這個事情吧。因此,我們可以做一個代理 ,吃蘋果之前,先把它削皮。 就像下面這樣,把原來的水果包一層:

//PeelFruitProxy.java/**
 * 代理,讓每個水果去皮
 */public class PeelFruitProxy implements Fruit {    private Fruit mFruit;    public PeelFruit(Fruit fruit) {        this.mFruit = fruit;
    }    @Override
    public String getName() {
        System.out.println("proxt:" + proxy.getClass().getName());        return "去皮的" + mFruit.getName();
    }
}

添加了測試類,測試類如下:

//Main.javapublic class Main {    public static void main(String[] args) {
        Apple apple=new Apple();//原始的蘋果
        Banana banana=new Banana();//原始的香蕉

        PeelFruitProxy peelApple=new PeelFruitProxy(apple);//代理,添加去皮功能
        PeelFruitProxy peelBanana=new PeelFruitProxy(banana);//代理,添加去皮功能
        System.out.println(peelApple.getName());
        System.out.println(peelBanana.getName());
    }
}

以上就是Java的靜態代理,簡單點說,就是把原來的目標對象包一層,加入新東西再去調用目標本身。 但是如果只是這樣的靜態代理,一個接口,就需要一個代理,實現起來是不是很繁瑣。

Java的動態代理

在Java中,有一個干這個事情的類,叫做Proxy,可以直接使用反射方式,代理攔截。 先簡單的介紹一下這個類,其實最常用的只有一個靜態方法Proxt.newProxyInstance(),是這樣的:

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

首先我們要實現InvocationHandler,實現其中的invoke方法,在調用目標對象的時候,會先調用到invoke方法,需要實現者在這個方法中,在主動調用被調用者方法。

//FruitInvocationHandler.java/**
 * 調用方法攔截器
 */public class FruitInvocationHandler implements InvocationHandler {    private Fruit mFruit;    public FruitInvocationHandler(Fruit fruit) {        this.mFruit = fruit;
    }    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String result = (String) method.invoke(mFruit, args);//需要在這個方法里面,主動調用被代理的對象。
        return "去皮的" + result;
    }
}

運行一下:

//Main.Javapublic class Main {    public static void main(String[] args) {
        Apple apple = new Apple();
        Fruit proxyApple = (Fruit) Proxy.newProxyInstance(Fruit.class.getClassLoader(), new Class[]{Fruit.class}, new FruitInvocationHandler(apple));
        System.out.println(proxyApple.getClass().getName());
        System.out.println(proxyApple.getName());

        Banana banana = new Banana();
        Fruit proxyBanana = (Fruit) Proxy.newProxyInstance(Fruit.class.getClassLoader(), new Class[]{Fruit.class}, new FruitInvocationHandler(banana));
        System.out.println(proxyApple.getClass().getName());
        System.out.println(proxyBanana.getName());
    }
}

java中的代理是指什么

這個方法,就是生成一個上文中的PeelFruitProxy(當然,我們看到的他名字叫:com.sun.proxy.$Proxy0),動態的生成,避免每次都需要寫,這個也是叫他動態代理的原因,因為我們可以在運行時代理任意類。 很多程序中的AOP就是這樣實現的,但是我們發現一些特點,newProxyInstance()的第二個參數,是一個interfaces的列表,為啥要有這個這個列表呢?

因為我們動態生成的代理類,也需要實現接口,這樣才方便向下轉型,使用其中的方法,不然,生成的類,類名就是com.sun.proxy.$Proxy0這種,并且是在內存中,無法調用生成的方法。 ** 所以,這種動態代理的方法,有一個致命的缺點,那就是被代理的類,必須要實現接口。**

CGLib代理

cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime.

另一個大名鼎鼎的Java代理實現,就是CGLib(Code Generation Library),一個基于ASM的代碼生成框架,可以用他來動態生成類,然后實現對方法的攔截,就可以避開JDK的動態代理, 必須要目標類實現接口的問題了。 也就是說,可以用CGLib來生成上文中的PeelFruitProxy。

簡單介紹一下怎么用,首先這個CGLib是一個三方的庫,我們要把它依賴進來:

compile 'cglib:cglib:3.2.8'

最新版本可以在這里看(新版本)[https://github.com/cglib/cglib/releases] 然后我們來試一試,我們來實現一下上面的代理

//FruitMethodInterceptor.java/**
 * CGLib代理的方法攔截器
 */public class FruitMethodInterceptor implements MethodInterceptor{    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        String result = (String) proxy.invokeSuper(obj, args);//主要,這里調用的是父類,也就是說, 生成的類和原始類是繼承關系
        return "去皮的"+result;
    }
}//Main.javapublic class Main {    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Apple.class);
        enhancer.setCallback(new FruitMethodInterceptor());
        Apple apple = (Apple) enhancer.create();
        System.out.println(apple.getClass().getName());
        System.out.println(apple.getName());
    }
}

運行效果如下:

java中的代理是指什么

我們看到,實現了同樣的功能,但是,Apple已經不是原來的Apple類了,變成了com.zjiecode.learn.java.proxy.Apple$$EnhancerByCGLIB$$44ade224,沒錯,我們正真使用的是這個類,而不是原來的Apple了,這個類繼承自Apple,最后實現了對Apple類的代理。 這種方式,因為使用的是繼承,所以,無需被代理的類實現接口。當然,他也可以通過接口來實現代理。

總結

第一種代理,就不說了,只適合單一的一個接口的代理,在編譯時就決定好了。

第二、三種代理,都是動態時代理 ,但是我們看到也有差別:

1)JDK的動態代理 ,只能實現接口代理,并且是包裝的被代理對象(類的實例),也就是說,在代理的過程中,有2個對象,一個代理對象,一個目標對象,目標對象被包裝在代理對象里面。

2)CGLib的代理,是繼承目標對象,生成了一個新的類,然后來實現代理,這樣,在內存中就是有代理對象,沒有目標對象了,使用的是直接繼承的方式

生成代理類是在運行時,有別于javapoet在編譯時生成類。

以上就是java中的代理,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

饶平县| 金坛市| 唐河县| 峡江县| 察雅县| 翁源县| 舒城县| 若羌县| 青岛市| 雅江县| 偏关县| 孟州市| 石泉县| 阳城县| 定南县| 德保县| 汉源县| 洛川县| 大荔县| 凤翔县| 海南省| 湘潭市| 余姚市| 巴林左旗| 崇礼县| 汽车| 红原县| 柘荣县| 新竹市| 遂川县| 昭苏县| 高邮市| 姚安县| 沁水县| 平度市| 楚雄市| 香河县| 永新县| 曲阜市| 东丰县| 五河县|