動態代理


靜態代理

  • 創建一個接口,然后創建目標類實現該接口並且實現該接口中的抽象方法。之后再創建一個代理類,同時使其也實現這個接口。在代理類中持有一個目標對象的引用,而后在代理類方法中調用該對象的方法

動態代理

  • 利用反射機制在運行時動態創建代理類
  • JDK動態代理使用步驟
    • 創建被代理的接口和類
    • 創建InvocationHandler接口的實現類,重寫invoke方法,在invoke方法中實現代理邏輯
    • 通過Proxy的靜態方法newProxyInstance( ClassLoaderloader, Class[] interfaces, InvocationHandler h)創建一個代理對象
      • ClassLoaderloader 在哪個類里創建代理對象,就傳入該類的類加載器
      • Class[] interfaces 代理類需要實現的接口
      • InvocationHandler 代理邏輯對象
    • 使用代理對象

實現原理

  • 在Proxy.newProxyInstanceProxy方法內部,會調用Generator類的generateProxyClass()方法來生成代理類的字節碼,需要傳入參數:代理類需要實現的接口數組
  • generateProxyClass()方法根據傳入的接口數組,動態的成Class文件,包括字段和方法
  • JDK動態代理產生的代理類【繼承】Proxy類,java是單繼承,jdk動態代理是以實現接口的方式來執行的,並且【實現】接口數組中所有的接口
  • 代理類只有唯一構造方法,參數是InvocationHandlerd對象;構造方法內部邏輯是,把InvocationHandler對象傳給父類Proxy類,也就是把InvocationHandler對象注入到Proxy類當中
  • 在創建InvocationHandlerd對象的時候,我們可以選擇把目標對象注入到了InvocationHandler對象中(目標對象注入到InvocationHandler中,InvocationHandler對象注入到Proxy中)
  • 在使用代理類時,執行相應方法時,代理對象調用的是父類(Proxy類)中InvocationHandler對象的invoke方法,也就是我們之前重寫的invoke方法:代理邏輯在此方法內
  • 在InvocationHandler對象的invoke方法內,除了代理邏輯,還可以調用目標對象的方法(在創建InvocationHandler對象時,目標對象注入到了InvocationHandler中)

示例demo

  • 目標接口
package Proxy;
public interface UserService {
    public String getName(String userId);
}
  • 目標實現類
package Proxy;
public class UserServiceImpl implements UserService{
    @Override
    public String getName(String userId) {
        System.out.println("hello");
        return userId;
    }
}
  • InvocationHandler實現類
package Proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

class MyInvocationHandler implements InvocationHandler {

    private Object object; //目標對象

    //通過構造方法,把目標對象進入進來
    public MyInvocationHandler(Object object){
        this.object = object;
    }

    //代理邏輯
     /***
     * @param proxy 生成的代理對象
     * @param method 代理對象中要執行的方法
     * @param args 方法參數
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置代理邏輯");
        Object object = method.invoke(this.object, args);//除了代理邏輯,還可以選擇調用目標對象的方法;this.object為注入的目標對象
        System.out.println("后置代理邏輯");
        return object;
    }
}

  • main方法測試
public class ZhuydProxy {
    public static void main(String[] args) throws IOException {
        UserService target = new UserServiceImpl(); //創建目標對象
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(target); //創建代理邏輯對象,目標對象注入到InvocationHandler中
        UserService userService = (UserService) Proxy.newProxyInstance(ZhuydProxy.class.getClassLoader(),
                target.getClass().getInterfaces(),
                myInvocationHandler
        );//通過JDK動態代理,創建代理對象
        userService.getName("123");//運用代理對象
    }
  • 運行結果
前置代理邏輯
hello
后置代理邏輯

查看動態代理生成的字節碼文件到底張什么樣

  • 通過ProxyGenerator.generateProxyClass( 生成的代理類名字 , 代理接口數組 ) 方法生成:代理字節碼文件
  • 執行以下代碼
byte[] bytes = ProxyGenerator.generateProxyClass("UserService$proxy",new Class[]{UserService.class});
Path path = new File("C:\\UserService$proxy.class").toPath();
Files.write(path,bytes);
  • 生成的字節碼文件
import Proxy.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class UserService$proxy extends Proxy implements UserService {
    private static Method m1;
    private static Method m2;
    private static Method m0;
    private static Method m3;

    public UserService$proxy(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String getName(String var1) throws  {
        try {
            return (String)super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m3 = Class.forName("Proxy.UserService").getMethod("getName", Class.forName("java.lang.String"));
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}



原創,如需轉載請標明出處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM