java中的动态代理

java中的动态代理

java动态代理,我理解就是通过jvm本身,去生成class的字节码,生成的class文件是通过集成proxy,实现传入的接口来调用执行InvocationHandler里的方法.

先建立一个接口

package com.blaaair.proxy;

public interface UserInterface {

    void query();

    void select();
}

实现类

package com.blaaair.proxy;

public class UserImpl implements UserInterface {
    public void query() {
        System.out.println("query");
    }

    public void select() {
        System.out.println("select");
    }
}

InvocationHandler

package com.blaaair.proxy;

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

public class MyInvocationHandler implements InvocationHandler {

    private UserImpl user;

    public MyInvocationHandler(UserImpl user) {
        this.user = user;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("-----before----");
        Object invoke = method.invoke(user);
        System.out.println("----after----");
        return invoke;
    }
}

Main

package com.blaaair.proxy;

import sun.misc.ProxyGenerator;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        // 生成代理类
        UserInterface proxy = (UserInterface) Proxy.newProxyInstance(
                Main.class.getClassLoader(), UserImpl.class.getInterfaces(),
                new MyInvocationHandler(new UserImpl()));
        proxy.query();
        proxy.select();
        //利用java反射提供的生成器获取到class字节
        byte[] tests = ProxyGenerator.generateProxyClass("test",  UserImpl.class.getInterfaces());
        try {
            // 输出到文件
            OutputStream outputStream = new FileOutputStream(new File("D://test.class"));
            outputStream.write(tests);
            outputStream.flush();
            outputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 利用classLoader读取到动态代理的class,通过class创建代理对象
        try {
            Class<?> test = Main.class.getClassLoader().loadClass("test");
            Constructor<?> constructor = test.getConstructor(InvocationHandler.class);
            UserInterface proxy2 = (UserInterface) constructor.newInstance(new MyInvocationHandler(new UserImpl()));
            proxy2.query();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

查看生成的class结构

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import com.blaaair.proxy.UserInterface;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class test extends Proxy implements UserInterface {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m4;
    private static Method m0;

    public test(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 void query() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    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 void select() throws  {
        try {
            super.h.invoke(this, m4, (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);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("com.blaaair.proxy.UserInterface").getMethod("query");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m4 = Class.forName("com.blaaair.proxy.UserInterface").getMethod("select");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

解释

  1. public test(InvocationHandler var1) throws : 构造器传入InvocationHandler
  2. test extends Proxy implements UserInterface : 这点就可以说为什么jdk动态代理必须有接口
  3. super.h.invoke(this, m4, (Object[])null); : 从这就会调用到InvocationHandler的invoke方法,也就是说明什么? 执行自己实现InvocationHandler的类中invoke方法!!!

java中的动态代理
https://www.blaaair.com/archives/java%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86
作者
Glo6f
发布于
2022年09月22日
许可协议