大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節(jié)點(diǎn)LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 什么是動態(tài)代理

什么是動態(tài)代理

更新時(shí)間:2022-05-13 09:31:35 來源:動力節(jié)點(diǎn) 瀏覽737次

1.簡介

這篇文章是關(guān)于Java 的動態(tài)代理——它是我們在語言中可用的主要代理機(jī)制之一。

簡單地說,代理是通過自己的設(shè)施(通常是真實(shí)方法)傳遞函數(shù)調(diào)用的前端或包裝器——可能會添加一些功能。

動態(tài)代理允許使用一種方法的單個類為具有任意數(shù)量方法的任意類的多個方法調(diào)用提供服務(wù)。動態(tài)代理可以被認(rèn)為是一種外觀,但它可以偽裝成任何接口的實(shí)現(xiàn)。在幕后,它將所有方法調(diào)用路由到單個處理程序——invoke ()方法。

雖然它不是用于日常編程任務(wù)的工具,但動態(tài)代理對于框架編寫者來說非常有用。它也可以用于那些直到運(yùn)行時(shí)才知道具體類實(shí)現(xiàn)的情況。

此功能內(nèi)置在標(biāo)準(zhǔn) JDK 中,因此不需要額外的依賴項(xiàng)。

2.調(diào)用處理程序

讓我們構(gòu)建一個簡單的代理,它實(shí)際上不做任何事情,除了打印請求調(diào)用的方法并返回一個硬編碼的數(shù)字。

首先,我們需要創(chuàng)建java.lang.reflect.InvocationHandler的子類型:

public class DynamicInvocationHandler implements InvocationHandler {
    private static Logger LOGGER = LoggerFactory.getLogger(
      DynamicInvocationHandler.class);
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) 
      throws Throwable {
        LOGGER.info("Invoked method: {}", method.getName());
        return 42;
    }
}

在這里,我們定義了一個簡單的代理,它記錄調(diào)用了哪個方法并返回 42。

3. 創(chuàng)建代理實(shí)例

我們剛剛定義的調(diào)用處理程序所服務(wù)的代理實(shí)例是通過對java.lang.reflect.Proxy類的工廠方法模式調(diào)用創(chuàng)建的:

Map proxyInstance = (Map) Proxy.newProxyInstance(
  DynamicProxyTest.class.getClassLoader(), 
  new Class[] { Map.class }, 
  new DynamicInvocationHandler());

一旦我們有了代理實(shí)例,我們就可以正常調(diào)用它的接口方法:

proxyInstance.put("hello", "world");

正如預(yù)期的那樣,在日志文件中會打印出有關(guān)調(diào)用put()方法的消息。

4. 通過 Lambda 表達(dá)式調(diào)用處理程序

由于InvocationHandler是一個函數(shù)式接口,因此可以使用 lambda 表達(dá)式內(nèi)聯(lián)定義處理程序:

Map proxyInstance = (Map) Proxy.newProxyInstance(
  DynamicProxyTest.class.getClassLoader(), 
  new Class[] { Map.class }, 
  (proxy, method, methodArgs) -> {
    if (method.getName().equals("get")) {
        return 42;
    } else {
        throw new UnsupportedOperationException(
          "Unsupported method: " + method.getName());
    }
});

在這里,我們定義了一個處理程序,它為所有 get 操作返回 42,并為其他所有操作拋出UnsupportedOperationException。

它以完全相同的方式調(diào)用:

(int) proxyInstance.get("hello"); // 42
proxyInstance.put("hello", "world"); // exception

5.定時(shí)動態(tài)代理示例

讓我們來看看動態(tài)代理的一種潛在的真實(shí)世界場景。

假設(shè)我們想記錄我們的函數(shù)執(zhí)行需要多長時(shí)間。為此,我們首先定義一個能夠包裝“真實(shí)”對象、跟蹤時(shí)間信息和反射調(diào)用的處理程序:

public class TimingDynamicInvocationHandler implements InvocationHandler {
    private static Logger LOGGER = LoggerFactory.getLogger(
      TimingDynamicInvocationHandler.class);    
    private final Map<String, Method> methods = new HashMap<>();
    private Object target;
    public TimingDynamicInvocationHandler(Object target) {
        this.target = target;
        for(Method method: target.getClass().getDeclaredMethods()) {
            this.methods.put(method.getName(), method);
        }
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) 
      throws Throwable {
        long start = System.nanoTime();
        Object result = methods.get(method.getName()).invoke(target, args);
        long elapsed = System.nanoTime() - start;
        LOGGER.info("Executing {} finished in {} ns", method.getName(), 
          elapsed);
        return result;
    }
}

隨后,此代理可用于各種對象類型:

Map mapProxyInstance = (Map) Proxy.newProxyInstance(
  DynamicProxyTest.class.getClassLoader(), new Class[] { Map.class }, 
  new TimingDynamicInvocationHandler(new HashMap<>()));
mapProxyInstance.put("hello", "world");
CharSequence csProxyInstance = (CharSequence) Proxy.newProxyInstance(
  DynamicProxyTest.class.getClassLoader(), 
  new Class[] { CharSequence.class }, 
  new TimingDynamicInvocationHandler("Hello World"));
csProxyInstance.length()

在這里,我們代理了一個地圖和一個字符序列(字符串)。

代理方法的調(diào)用將委托給被包裝的對象并產(chǎn)生日志語句:

Executing put finished in 19153 ns 
Executing get finished in 8891 ns 
Executing charAt finished in 11152 ns 
Executing length finished in 10087 ns

以上就是關(guān)于“什么是動態(tài)代理”的介紹,大家如果對此比較感興趣,想了解更多相關(guān)知識,可以關(guān)注一下動力節(jié)點(diǎn)的Java在線學(xué)習(xí),里面的課程內(nèi)容細(xì)致全面,很適合沒有基礎(chǔ)的小伙伴學(xué)習(xí),希望對大家能夠有所幫助哦。

提交申請后,顧問老師會電話與您溝通安排學(xué)習(xí)

免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 欧美日本一道高清免费3区 欧美日本一道免费一区三区 | 日韩欧美一区二区三区四区 | 欧美福利视频在线观看 | 国产精品亚洲第一区二区三区 | 日本视频在线观看不卡高清免费 | 波多野结衣中文字幕久久 | 日韩一中文字幕 | 成人www| 欧美另类亚洲 | 国产区免费 | 日韩不卡一区二区三区 | 亚洲精品专区一区二区三区 | 狠狠的日视频 | 国产视频久久久久 | 九九视频免费在线观看 | 久久九九99热这里只有精品 | 国产不卡免费视频 | 九色视频极品论坛区 | 亚洲免费区 | 人人干在线观看 | 成年女人毛片免费视频 | 久久中文字幕视频 | 亚洲精品麻豆一区二区 | 伊人久久亚洲综合 | 色老头在线观看精品 | 就草草在线观看视频 | 久久美女精品国产精品亚洲 | 日本在线毛片视频免费看 | 米奇777第四久久久99 | 亚洲一级毛片欧美一级说乱 | 香蕉视频在线观看网站 | 在线免费观看一区二区三区 | 福利影院第一页 | 亚洲第一区二区快射影院 | 免费久久久久 | 永久久久免费浮力影院 | 亚洲精品 国产 日韩 | 精品亚洲综合久久中文字幕 | 全免费a级毛片免费看不卡 全免费a级毛片免费看视频免 | 亚洲欧洲一二三区机械有限公司 | 国产欧美在线观看视频 |