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

淺談Java 代理機(jī)制

 更新時間:2021年06月21日 14:49:25   作者:飛天小牛肉  
Java 有兩種代理方式,一種是靜態(tài)代理,另一種是動態(tài)代理。如果我們在代碼編譯時就確定了被代理的類是哪一個,那么就可以直接使用靜態(tài)代理;如果不能確定,那么可以使用類的動態(tài)加載機(jī)制,在代碼運(yùn)行期間加載被代理的類這就是動態(tài)代理

一、常規(guī)編碼方式

在學(xué)習(xí)代理之前,先回顧以下我們的常規(guī)編碼方式:所有 interface 類型的變量總是通過向上轉(zhuǎn)型并指向某個實例的。

1)首先,定義一個接口:

public interface SmsService {
    String send(String message);
}

2)然后編寫其實現(xiàn)類:

public class SmsServicseImpl implements SmsService {
    public String send(String message) {
        System.out.println("send message:" + message);
        return message;
    }
}

3)最后創(chuàng)建該實現(xiàn)類的實例,轉(zhuǎn)型為接口并調(diào)用:

SmsService s = new SmsServicseImpl();
s.send("Java");

上述這種方式就是我們通常編寫代碼的方式。而代理模式和這種方式有很大的區(qū)別,且看下文。

二、代理模式概述

簡單來說,代理模式就是 使用代理對象來代替對真實對象的訪問,這樣就可以在不修改原目標(biāo)對象的前提下,提供額外的功能操作,擴(kuò)展目標(biāo)對象的功能。

代理模式大致有三種角色:

  • Real Subject:真實類,也就是被代理類、委托類。用來真正完成業(yè)務(wù)服務(wù)功能;
  • Proxy:代理類。將自身的請求用 Real Subject 對應(yīng)的功能來實現(xiàn),代理類對象并不真正的去實現(xiàn)其業(yè)務(wù)功能;
  • Subject:定義 RealSubject 和 Proxy 角色都應(yīng)該實現(xiàn)的接口。

通俗來說,代理模式的主要作用是擴(kuò)展目標(biāo)對象的功能,比如說在目標(biāo)對象的某個方法執(zhí)行前后你可以增加一些額外的操作,并且不用修改這個方法的原有代碼。如果大家學(xué)過 Spring 的 AOP,一定能夠很好的理解這句話。

舉個例子:你找了小紅來幫你向小綠問話,小紅就看作是代理我的代理類 Proxy,而你是 Real Subject,因為小紅要傳達(dá)的話其實是你說的。那么你和小紅都需要實現(xiàn)的接口(Subject)就是說話,由于你倆都能說話,在外界看來你倆就是一樣的(滑稽,大家理解就好,不用較真)

看到這里,不知道大家能不能理解了為什么委托類和代理類都需要實現(xiàn)相同的接口?

那是為了保持行為的一致性,在訪問者看來兩者之間就沒有區(qū)別。這樣,通過代理類這個中間層,很好地隱藏和保護(hù)了委托類對象,能有效屏蔽外界對委托類對象的直接訪問。同時,也可以在代理類上加上額外的操作,比如小紅在說話之前會跳一段舞,外界就會覺得你在說話前會跳一段舞,所以,這就實現(xiàn)了委托類的功能增強(qiáng)。

代理模式有靜態(tài)代理和動態(tài)代理兩種實現(xiàn)方式。

三、靜態(tài)代理

3.1、什么是靜態(tài)代理

先來看靜態(tài)代理的實現(xiàn)步驟:

1)定義一個接口(Subject)

2)創(chuàng)建一個委托類(Real Subject)實現(xiàn)這個接口

3)創(chuàng)建一個代理類(Proxy)同樣實現(xiàn)這個接口

4)將委托類 Real Subject 注入進(jìn)代理類 Proxy,在代理類的方法中調(diào)用 Real Subject 中的對應(yīng)方法。這樣的話,我們就可以通過代理類屏蔽對目標(biāo)對象的訪問,并且可以在目標(biāo)方法執(zhí)行前后做一些自己想做的事情。

從實現(xiàn)和應(yīng)用角度來說,靜態(tài)代理中,我們對目標(biāo)對象的每個方法的增強(qiáng)都是手動完成的,非常不靈活(比如接口一旦新增加方法,目標(biāo)對象和代理對象都要進(jìn)行修改)且麻煩(需要對每個目標(biāo)類都單獨寫一個代理類)。 實際應(yīng)用場景非常非常少,日常開發(fā)幾乎看不到使用靜態(tài)代理的場景。

從 JVM 層面來說, 靜態(tài)代理在編譯時就將接口、委托類、代理類這些都變成了一個個實際的 .class 文件。

3.2、代碼示例

1)定義發(fā)送短信的接口

public interface SmsService {
    String send(String message);
}

2)創(chuàng)建一個委托類(Real Subject)實現(xiàn)這個接口

public class SmsServiceImpl implements SmsService {
    public String send(String message) {
        System.out.println("send message:" + message);
        return message;
    }
}

3)創(chuàng)建一個代理類(Proxy)同樣實現(xiàn)這個接口

4)將委托類 Real Subject 注入進(jìn)代理類 Proxy,在代理類的方法中調(diào)用 Real Subject 中的對應(yīng)方法。這樣的話,我們就可以通過代理類屏蔽對目標(biāo)對象的訪問,并且可以在目標(biāo)方法執(zhí)行前后做一些自己想做的事情。

public class SmsProxy implements SmsService {
    
    // 將委托類注入進(jìn)代理類
    private final SmsService smsService;
​
    public SmsProxy(SmsService smsService) {
        this.smsService = smsService;
    }
​
    @Override
    public String send(String message) {
        // 調(diào)用委托類方法之前,我們可以添加自己的操作
        System.out.println("before method send()");
        // 調(diào)用委托類方法
        smsService.send(message); 
        // 調(diào)用委托類方法之后,我們同樣可以添加自己的操作
        System.out.println("after method send()");
        return null;
    }
}

那么,如何使用這個被增強(qiáng)的 send 方法呢?

public class Main {
    public static void main(String[] args) {
        SmsService smsService = new SmsServiceImpl();
        SmsProxy smsProxy = new SmsProxy(smsService);
        smsProxy.send("Java");
    }
}

運(yùn)行上述代碼之后,控制臺打印出:

before method send()

send message:java

after method send()

從輸出結(jié)果可以看出,我們已經(jīng)增強(qiáng)了委托類 SmsServiceImplsend() 方法。

當(dāng)然,從上述代碼我們也能看出來,靜態(tài)代理存在一定的弊端。假如說我們現(xiàn)在新增了一個委托類實現(xiàn)了 SmsService 接口,如果我們想要對這個委托類進(jìn)行增強(qiáng),就需要重新寫一個代理類,然后注入這個新的委托類,非常不靈活。也就是說靜態(tài)代理是一個委托了對應(yīng)一個代理類,能不能將代理類做成一個通用的呢?為此,動態(tài)代理應(yīng)用而生。

四、Java 字節(jié)碼生成框架

在講解動態(tài)之前,我們有必要詳細(xì)說一下 .class 字節(jié)碼文件這個東西。動態(tài)代理機(jī)制和 Java 字節(jié)碼生成框架息息相關(guān)。

在上文反射中我們提到,一個 Class 類對應(yīng)一個 .class 字節(jié)碼文件,也就說字節(jié)碼文件中存儲了一個類的全部信息。字節(jié)碼其實是二進(jìn)制文件,內(nèi)容是只有 JVM 能夠識別的機(jī)器碼。

解析過程這樣的:JVM 讀取 .class 字節(jié)碼文件,取出二進(jìn)制數(shù)據(jù),加載到內(nèi)存中,解析字節(jié)碼文件內(nèi)的信息,生成對應(yīng)的 Class 類對象:

顯然,上述這個過程是在編譯期就發(fā)生的。

那么,由于JVM 是通過 .class 字節(jié)碼文件(也就是二進(jìn)制信息)加載類的,如果我們在運(yùn)行期遵循 Java 編譯系統(tǒng)組織 .class 字節(jié)碼文件的格式和結(jié)構(gòu),生成相應(yīng)的二進(jìn)制數(shù)據(jù),然后再把這個二進(jìn)制數(shù)據(jù)加載轉(zhuǎn)換成對應(yīng)的類。這樣,我們不就完成了在運(yùn)行時動態(tài)的創(chuàng)建一個類。這個思想其實也就是動態(tài)代理的思想。

在運(yùn)行時期按照 JVM 規(guī)范對 .class 字節(jié)碼文件的組織規(guī)則,生成對應(yīng)的二進(jìn)制數(shù)據(jù)。當(dāng)前有很多開源框架可以完成這個功能,如

  • ASM
  • CGLIB
  • Javassist
  • ......

需要注意的是,CGLIB 是基于 ASM 的。 這里簡單對比一下 ASM 和 Javassist:

  • Javassist 源代碼級 API 比 ASM 中實際的字節(jié)碼操作更容易使用
  • Javassist 在復(fù)雜的字節(jié)碼級操作上提供了更高級別的抽象層。Javassist 源代碼級 API 只需要很少的字節(jié)碼知識,甚至不需要任何實際字節(jié)碼知識,因此實現(xiàn)起來更容易、更快。
  • Javassist 使用反射機(jī)制,這使得它比 ASM 慢。

總的來說 ASM 比 Javassist 快得多,并且提供了更好的性能,但是 Javassist 相對來說更容易使用,兩者各有千秋。

以 Javassist 為例,我們來看看這些框架在運(yùn)行時生成 .class 字節(jié)碼文件的強(qiáng)大能力。

正常來說,我們創(chuàng)建一個類的代碼是這樣的:

package com.samples;
​
public class Programmer {
    public void code(){
        System.out.println("I'm a Programmer,Just Coding.....");
    }
}

下面通過 Javassist 創(chuàng)建和上面一模一樣的 Programmer 類的字節(jié)碼:

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
​
public class MyGenerator {
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        // 創(chuàng)建 Programmer 類      
        CtClass cc= pool.makeClass("com.samples.Programmer");
        // 定義方法
        CtMethod method = CtNewMethod.make("public void code(){}", cc);
        // 插入方法代碼
        method.insertBefore("System.out.println(\"I'm a Programmer,Just Coding.....\");");
        cc.addMethod(method);
        // 保存生成的字節(jié)碼
        cc.writeFile("d://temp");
    }
}

通過反編譯工具打開 Programmer.class 可以看到以下代碼:

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

OK,了解了 Java 字節(jié)碼生成框架,可以開始學(xué)習(xí)動態(tài)代理(Dynamic Proxy)了。

回顧一下靜態(tài)代理,我們把靜態(tài)代理的執(zhí)行過程抽象為下圖:

可以看見,代理類無非是在調(diào)用委托類方法的前后增加了一些操作。委托類的不同,也就導(dǎo)致代理類的不同。

那么為了做一個通用性的代理類出來,我們把調(diào)用委托類方法的這個動作抽取出來,把它封裝成一個通用性的處理類,于是就有了動態(tài)代理中的 InvocationHandler 角色(處理類)。

于是,在代理類和委托類之間就多了一個處理類的角色,這個角色主要是對代理類調(diào)用委托類方法的這個動作進(jìn)行統(tǒng)一的調(diào)用,也就是由 InvocationHandler 來統(tǒng)一處理代理類調(diào)用委托類方法這個操作??聪聢D:

從 JVM 角度來說,動態(tài)代理是在運(yùn)行時動態(tài)生成 .class 字節(jié)碼文件 ,并加載到 JVM 中的。這個我們在 Java 字節(jié)碼生成框架中已經(jīng)提到過。

雖然動態(tài)代理在我們?nèi)粘i_發(fā)中使用的相對較少,但是在框架中的幾乎是必用的一門技術(shù)。學(xué)會了動態(tài)代理之后,對于我們理解和學(xué)習(xí)各種框架的原理也非常有幫助,Spring AOP、RPC 等框架的實現(xiàn)都依賴了動態(tài)代理。

就 Java 來說,動態(tài)代理的實現(xiàn)方式有很多種,比如:

  • JDK 動態(tài)代理
  • CGLIB 動態(tài)代理
  • Javassit 動態(tài)代理
  • ......

下面詳細(xì)講解這三種動態(tài)代理機(jī)制。

六、JDK 動態(tài)代理機(jī)制

6.1、使用步驟

先來看下 JDK 動態(tài)代理機(jī)制的使用步驟:

1)定義一個接口(Subject)

2)創(chuàng)建一個委托類(Real Subject)實現(xiàn)這個接口

3)創(chuàng)建一個處理類并實現(xiàn) InvocationHandler 接口,重寫其 invoke 方法(在 invoke 方法中利用反射機(jī)制調(diào)用委托類的方法,并自定義一些處理邏輯),并將委托類注入處理類

該方法有下面三個參數(shù):

proxy:代理類對象(見下一步)

method:還記得我們在上篇文章反射中講到的 Method.invoke 嗎?就是這個,我們可以通過它來調(diào)用委托類的方法(反射)

args:傳給委托類方法的參數(shù)列表

4)創(chuàng)建代理對象(Proxy):通過 Proxy.newProxyInstance() 創(chuàng)建委托類對象的代理對象

這個方法需要 3 個參數(shù):

  • 類加載器 ClassLoader
  • 委托類實現(xiàn)的接口數(shù)組,至少需要傳入一個接口進(jìn)去
  • 調(diào)用的 InvocationHandler 實例處理接口方法(也就是第 3 步我們創(chuàng)建的類的實例)

也就是說:我們在通過 Proxy 類的 newProxyInstance() 創(chuàng)建的代理對象在調(diào)用方法的時候,實際會調(diào)用到實現(xiàn)了 InvocationHandler 接口的處理類的 invoke()方法,可以在 invoke() 方法中自定義處理邏輯,比如在方法執(zhí)行前后做什么事情。

6.2、代碼示例

1)定義一個接口(Subject)

public interface SmsService {
    String send(String message);
}

2)創(chuàng)建一個委托類(Real Subject)實現(xiàn)這個接口

public class SmsServiceImpl implements SmsService {
    public String send(String message) {
        System.out.println("send message:" + message);
        return message;
    }
}

3)創(chuàng)建一個處理類并實現(xiàn) InvocationHandler 接口,重寫其 invoke 方法(在 invoke 方法中利用反射機(jī)制調(diào)用委托類的方法,并自定義一些處理邏輯),并將委托類注入處理類

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
​
public class DebugInvocationHandler implements InvocationHandler {
    
    // 將委托類注入處理類(這里我們用 Object 代替,方便擴(kuò)展)
    private final Object target;
​
    public DebugInvocationHandler(Object target) {
        this.target = target;
    }
    
    // 重寫 invoke 方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
        //調(diào)用方法之前,我們可以添加自己的操作
        System.out.println("before method " + method.getName());
        Object result = method.invoke(target, args);
        //調(diào)用方法之后,我們同樣可以添加自己的操作
        System.out.println("after method " + method.getName());
        return result;
    }
}

4)定義一個創(chuàng)建代理對象(Proxy)的工廠類:通過 Proxy.newProxyInstance() 創(chuàng)建委托類對象的代理對象

public class JdkProxyFactory {
    public static Object getProxy(Object target) {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new DebugInvocationHandler(target)
        );
    }
}

5)實際使用

SmsService smsService = (SmsService) JdkProxyFactory.getProxy(new SmsServiceImpl());
smsService.send("Java");

運(yùn)行上述代碼之后,控制臺打印出:

before method send

send message:Java

after method send

七、CGLIB 動態(tài)代理機(jī)制

7.1、使用步驟

JDK 動態(tài)代理有一個最致命的問題是它只能代理實現(xiàn)了某個接口的實現(xiàn)類,并且代理類也只能代理接口中實現(xiàn)的方法,要是實現(xiàn)類中有自己私有的方法,而接口中沒有的話,該方法不能進(jìn)行代理調(diào)用。

為了解決這個問題,我們可以用 CGLIB 動態(tài)代理機(jī)制。

上文也提到過,CGLIB(Code Generation Library)是一個基于 ASM 的 Java 字節(jié)碼生成框架,它允許我們在運(yùn)行時對字節(jié)碼進(jìn)行修改和動態(tài)生成。原理就是通過字節(jié)碼技術(shù)生成一個子類,并在子類中攔截父類方法的調(diào)用,織入額外的業(yè)務(wù)邏輯。關(guān)鍵詞大家注意到?jīng)]有,攔截!CGLIB 引入一個新的角色就是方法攔截器 MethodInterceptor。和 JDK 中的處理類 InvocationHandler 差不多,也是用來實現(xiàn)方法的統(tǒng)一調(diào)用的。看下圖:

另外由于 CGLIB 采用繼承的方式,所以被代理的類不能被 final 修飾。

很多知名的開源框架都使用到了 CGLIB, 例如 Spring 中的 AOP 模塊中:如果目標(biāo)對象實現(xiàn)了接口,則默認(rèn)采用 JDK 動態(tài)代理,否則采用 CGLIB 動態(tài)代理。

來看 CGLIB 動態(tài)代理的使用步驟:

1)首先創(chuàng)建一個委托類(Real Subject)

2)創(chuàng)建一個方法攔截器實現(xiàn)接口 MethodInterceptor,并重寫 intercept 方法。intercept 用于攔截并增強(qiáng)委托類的方法(和 JDK 動態(tài)代理 InvocationHandler 中的 invoke 方法類似)

該方法擁有四個參數(shù):

  • Object var1:委托類對象
  • Method var2:被攔截的方法(委托類中需要增強(qiáng)的方法)
  • Object[] var3:方法入?yún)?/li>
  • MethodProxy var4:用于調(diào)用委托類的原始方法(底層也是通過反射機(jī)制,不過不是 Method.invoke 了,而是使用 MethodProxy.invokeSuper 方法)

3)創(chuàng)建代理對象(Proxy):通過 Enhancer.create() 創(chuàng)建委托類對象的代理對象

也就是說:我們在通過 Enhancer 類的 create() 創(chuàng)建的代理對象在調(diào)用方法的時候,實際會調(diào)用到實現(xiàn)了 MethodInterceptor 接口的處理類的 intercept()方法,可以在 intercept() 方法中自定義處理邏輯,比如在方法執(zhí)行前后做什么事情。

可以發(fā)現(xiàn),CGLIB 動態(tài)代理機(jī)制和 JDK 動態(tài)代理機(jī)制的步驟差不多,CGLIB 動態(tài)代理的核心是方法攔截器 MethodInterceptorEnhancer,而 JDK 動態(tài)代理的核心是處理類 InvocationHandlerProxy。

7.2、代碼示例

不同于 JDK 動態(tài)代理不需要額外的依賴。CGLIB 是一個開源項目,如果你要使用它的話,需要手動添加相關(guān)依賴。

<dependency>
  <groupId>cglib</groupId>
  <artifactId>cglib</artifactId>
  <version>3.3.0</version>
</dependency>

1)首先創(chuàng)建一個委托類(Real Subject)

public class AliSmsService {
    public String send(String message) {
        System.out.println("send message:" + message);
        return message;
    }
}

2)創(chuàng)建一個方法攔截器實現(xiàn)接口 MethodInterceptor,并重寫 intercept 方法

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class DebugMethodInterceptor implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        // 調(diào)用方法之前,我們可以添加自己的操作
        System.out.println("before method " + method.getName());
        // 通過反射調(diào)用委托類的方法
        Object object = methodProxy.invokeSuper(o, args);
        // 調(diào)用方法之后,我們同樣可以添加自己的操作
        System.out.println("after method " + method.getName());
        return object;
    }

}

3)創(chuàng)建代理對象(Proxy):通過 Enhancer.create() 創(chuàng)建委托類對象的代理對象

import net.sf.cglib.proxy.Enhancer;

public class CglibProxyFactory {
    public static Object getProxy(Class<?> clazz) {
        // 創(chuàng)建動態(tài)代理增強(qiáng)類
        Enhancer enhancer = new Enhancer();
        // 設(shè)置類加載器
        enhancer.setClassLoader(clazz.getClassLoader());
        // 設(shè)置委托類(設(shè)置父類)
        enhancer.setSuperclass(clazz);
        // 設(shè)置方法攔截器
        enhancer.setCallback(new DebugMethodInterceptor());
        // 創(chuàng)建代理類
        return enhancer.create();
    }
}

setSuperclass 我們就能看出,為什么說 CGLIB 是基于繼承的。

4)實際使用

AliSmsService aliSmsService = 
    (AliSmsService) CglibProxyFactory.getProxy(AliSmsService.class);
aliSmsService.send("Java");

運(yùn)行上述代碼之后,控制臺打印出:

before method send

send message:Java

after method send

JDK 動態(tài)代理和 CGLIB 動態(tài)代理對比

1)JDK 動態(tài)代理是基于實現(xiàn)了接口的委托類,通過接口實現(xiàn)代理;而 CGLIB 動態(tài)代理是基于繼承了委托類的子類,通過子類實現(xiàn)代理。

2)JDK 動態(tài)代理只能代理實現(xiàn)了接口的類,且只能增強(qiáng)接口中現(xiàn)有的方法;而 CGLIB 可以代理未實現(xiàn)任何接口的類。

3)就二者的效率來說,大部分情況都是 JDK 動態(tài)代理的效率更高,隨著 JDK 版本的升級,這個優(yōu)勢更加明顯。

常見的還有 Javassist 動態(tài)代理機(jī)制。和 CGLIB 一樣,作為一個 Java 字節(jié)碼生成框架,Javassist 天生就擁有在運(yùn)行時動態(tài)創(chuàng)建一個類的能力,實現(xiàn)動態(tài)代理自然不在話下。 Dubbo 就是默認(rèn)使用 Javassit 來進(jìn)行動態(tài)代理的。

八、什么情況下使用動態(tài)代理

1)設(shè)計模式中有一個設(shè)計原則是開閉原則,即對修改關(guān)閉,對擴(kuò)展開放,我們在工作中有時會接手很多前人的代碼,里面代碼邏輯讓人摸不著頭腦,就很難去下手修改代碼,那么這時我們就可以通過代理對類進(jìn)行增強(qiáng)。

2)我們在使用 RPC 框架的時候,框架本身并不能提前知道各個業(yè)務(wù)方要調(diào)用哪些接口的哪些方法 。那么這個時候,就可用通過動態(tài)代理的方式來建立一個中間人給客戶端使用,也方便框架進(jìn)行搭建邏輯,某種程度上也是客戶端代碼和框架松耦合的一種表現(xiàn)。

3)Spring 的 AOP 機(jī)制同樣也是采用了動態(tài)代理,此處不做詳細(xì)討論。

九、靜態(tài)代理和動態(tài)代理對比

1)靈活性 :動態(tài)代理更加靈活,不需要必須實現(xiàn)接口,可以直接代理實現(xiàn)類,并且可以不需要針對每個目標(biāo)類都創(chuàng)建一個代理類。另外,靜態(tài)代理中,接口一旦新增加方法,目標(biāo)對象和代理對象都要進(jìn)行修改,這是非常麻煩的

2)JVM 層面 :靜態(tài)代理在編譯時就將接口、實現(xiàn)類、代理類這些都變成了一個個實際的 .class 字節(jié)碼文件。而動態(tài)代理是在運(yùn)行時動態(tài)生成類字節(jié)碼,并加載到 JVM 中的。

十、總結(jié)

全部捋一遍下來還是收獲蠻多的,我感覺只要理解了字節(jié)碼在編譯期生成還是在運(yùn)行期生成,就差不多能夠把握住靜態(tài)代理和動態(tài)代理了??偨Y(jié)一下靜態(tài)代理和動態(tài)代理中的角色:

靜態(tài)代理:

Subject:公共接口

Real Subject:委托類

Proxy:代理類

JDK 動態(tài)代理:

Subject:公共接口

Real Subject:委托類

Proxy:代理類

InvocationHandler:處理類,統(tǒng)一調(diào)用方法

CGLIB 動態(tài)代理:

Subject:公共接口

Real Subject:委托類

Proxy:代理類

MethodInterceptor:方法攔截器,統(tǒng)一調(diào)用方法

以上就是淺談Java 代理機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于Java 代理機(jī)制的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Spring Boot + Mybatis 實現(xiàn)動態(tài)數(shù)據(jù)源

    詳解Spring Boot + Mybatis 實現(xiàn)動態(tài)數(shù)據(jù)源

    這篇文章主要介紹了Spring Boot + Mybatis 實現(xiàn)動態(tài)數(shù)據(jù)源,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • java?long?類型數(shù)據(jù)的賦值方式

    java?long?類型數(shù)據(jù)的賦值方式

    這篇文章主要介紹了java?long?類型數(shù)據(jù)的賦值方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • vue用CryptoJS加密,java用CryptoUtil解密

    vue用CryptoJS加密,java用CryptoUtil解密

    CryptoJS是一個JavaScript庫,提供了一系列密碼學(xué)函數(shù)和工具,用于加密、解密、生成摘要等任務(wù),本文vue前端使用CryptoJS加密,java后端使用CryptoUtil解密
    2024-09-09
  • Java一個簡單的紅包生成算法

    Java一個簡單的紅包生成算法

    今天小編就為大家分享一篇關(guān)于Java一個簡單的紅包生成算法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Java實現(xiàn)修改圖片文件名的方法示例

    Java實現(xiàn)修改圖片文件名的方法示例

    在很多應(yīng)用中,用戶需要對文件進(jìn)行重命名操作,包括圖片文件,圖片文件的重命名操作可以是基于文件內(nèi)容、日期、用戶輸入等,本項目的目標(biāo)是實現(xiàn)一個Java程序,能夠修改圖片文件的文件名,并進(jìn)行簡單的文件名處理,需要的朋友可以參考下
    2025-02-02
  • Java方法重載的使用實戰(zhàn)案例

    Java方法重載的使用實戰(zhàn)案例

    這篇文章主要介紹了Java方法重載的使用,結(jié)合具體實例形式分析了java方法重載的基本使用技巧與相關(guān)操作注意事項,需要的朋友可以參考下
    2019-09-09
  • Java使用Hutool實現(xiàn)AES、DES加密解密的方法

    Java使用Hutool實現(xiàn)AES、DES加密解密的方法

    本篇文章主要介紹了Java使用Hutool實現(xiàn)AES、DES加密解密的方法,具有一定的參考價值,有興趣的可以了解一下
    2017-08-08
  • java排查進(jìn)程占用系統(tǒng)內(nèi)存高方法

    java排查進(jìn)程占用系統(tǒng)內(nèi)存高方法

    這篇文章主要為大家介紹了java進(jìn)程占用系統(tǒng)內(nèi)存高排查方法,
    2023-06-06
  • IDEA使用學(xué)生郵箱無法注冊問題:JetBrains Account connection error: 拒絕連接

    IDEA使用學(xué)生郵箱無法注冊問題:JetBrains Account connection error: 拒絕連接

    這篇文章主要介紹了IDEA使用學(xué)生郵箱無法注冊問題:JetBrains Account connection error: 拒絕連接,文中通過圖文及示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java 多線程之兩步掌握

    Java 多線程之兩步掌握

    Java 多線程編程 Java給多線程編程提供了內(nèi)置的支持。一條線程指的是進(jìn)程中一個單一順序的控制流,一個進(jìn)程中可以并發(fā)多個線程,每條線程并行執(zhí)行不同的任務(wù)
    2021-10-10

最新評論

湖州市| 文山县| 莒南县| 苍山县| 宁国市| 湘潭县| 宜川县| 策勒县| 扎兰屯市| 洛浦县| 格尔木市| 彰化县| 溧水县| 许昌市| 肥东县| 忻城县| 仙桃市| 泗洪县| 遵化市| 紫阳县| 罗江县| 壤塘县| 泰宁县| 柏乡县| 镇康县| 安溪县| 鄯善县| 余江县| 江华| 塘沽区| 石泉县| 越西县| 北票市| 吴旗县| 余江县| 岗巴县| 封丘县| 民丰县| 集贤县| 武胜县| 平乡县|