源码解读-Java代理和代理模式(2021-10-8/9)

代理模式

理解

代理模式是一种设计模式,其意义是生成代理对象,通过控制代理对象来控制真实对象的访问

如rpc客户端中, 控制生成的消息代理对象(调用代理对象的方法),来完成对一次消息的封装,从而发送一个rpc请求

即完成在客户端封装一个调用服务端库对象,通过代理模式,控制代理对象,来完成实际的消息发送

代码

/**
 * @Author: jiangtao
 * @Date: 2021/10/8 18:57
 */
interface RPCServer {
    // add为调用server中标识的方法名, x|y 为参数 (lsp)
    int add(int x, int y);
}

class Proxy{
	
    // 由于这是一个接口,所以就不需要传入target Object
    public static <T> T getProxyService(Class<T> serviceClass){
        ClassLoader loader = serviceClass.getClassLoader();
        Class<?>[] interfaces = new Class[]{serviceClass};
        Object o = java.lang.reflect.Proxy.newProxyInstance(loader, interfaces, (proxy, method, args) -> {
            // 将调用方法转换为消息对象
            // 发送消息到server
            // 等待server返回结果
            // 返回结果
            // (可以讲以上步骤转换成一个Class)
            return 1;
        });
        return (T) o;
    }

}

class Test{
    public static void main(String[] args) {
        // 通过生成的代理对象,即可以调用方法
        // 来控制真正对象访问
        RPCServer rpcServer = Proxy.getProxyService(RPCServer.class);
        int res = rpcServer.add(1,2);
    }
}

静态代理和动态代理

静态代理需要手动生成代理对象

动态代理是在运行时自动创建代理对象并将其添加到JVM中

Java代理

Proxy&InvocationHandler

  • 上面代码

  • java.lang.reflect.Proxy.newProxyInstance即为InvocationHandler的唯一一个方法invoke

  • 代理之后,返回代理对象,代理对象的每一个方法的调用都是invoke的调用,只是参数不同

拦截器

import java.lang.reflect.Method;

/**
 * @Author: jiangtao
 * @Date: 2021/10/8 19:39
 */
public interface Interceptor {
    public boolean before(Object proxy, Object target, Method method, Object[] args);
    public void after(Object proxy, Object target, Method method, Object[] args);
}

class InterceptorProxy{
	// serviceClass每一次方法的调用,都将调用InvocationHandler.invoke
    public static <T> T getProxyService(Class<T> serviceClass, Interceptor interceptor, Object target){
        ClassLoader loader = serviceClass.getClassLoader();
        Class<?>[] interfaces = new Class[]{serviceClass};
        // proxy 代理对象, method 调用方法 , args 调用参数
        Object o = java.lang.reflect.Proxy.newProxyInstance(loader, interfaces, (proxy, method, args) -> {
            Object result = null;
            if (interceptor == null) result = method.invoke(target, args);
            if (interceptor.before(proxy, target, method, args)) result = method.invoke(target, args);
            interceptor.after(proxy, target, method, args);
            return result;
        });
        // 代理对象
        return (T) o;
    }
}

// 上述代理:将target所有方法调用,放到一个方法中,用不同逻辑调用
interface Client{
    String sayHello(String name);
}

class TestProxy{
    public static void main(String[] args) {
        Client client = InterceptorProxy.getProxyService(Client.class, new Interceptor() {
            @Override
            public boolean before(Object proxy, Object target, Method method, Object[] args) {
                System.out.println("---before---");
                return true;
            }

            @Override
            public void after(Object proxy, Object target, Method method, Object[] args) {
                System.out.println("---after---");
            }
        }, new Client() {
            @Override
            public String sayHello(String name) {
                System.out.println("hello~ " + name);
                return name;
            }
        });

        System.out.println(client.sayHello("me"));
    }
}

自动生成的代理对象Class文件

// 通过反编译查看源代码
byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Client.class});
// JDK8之后不可在包外调用
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import test.Client;

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

    public $Proxy0(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 sayHello(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);
        }
    }

    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);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("test.Client").getMethod("sayHello", Class.forName("java.lang.String"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
  • 可见该Class继承Client接口,当该对象调用时,自动调用invoke方法(其中可以调用实际client方法)

手写Proxy&Invocationhanddler

package test;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: jiangtao
 * @Date: 2021/10/9 17:29
 */
public interface MyInvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

// Proxy
class MyProxy{
    public static final String ln = "\r\n";

    public static Object newProxyInstance(MyClassLoader classLoader, Class<?> [] interfaces, MyInvocationHandler h){
        try {
            // 动态生成源码.java文件
            String src = generateSrc(interfaces);
            // 文件输出到磁盘, 编译之后的Class文件的路径
            String filePath = MyProxy.class.getResource("").getPath();
            File f = new File(filePath + "$Proxy0.java");
            FileWriter fw = new FileWriter(f);
            fw.write(src);
            fw.flush();
            fw.close();
            
            // java文件转换为Class文件
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
            Iterable iterable = manager.getJavaFileObjects(f);
            
            JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
            task.call();
            manager.close();
            
            // 编译生成的class文件加载到JVM中
            Class proxyClass = classLoader.findClass("$Proxy0");
            // 以参数的形式参入My
            Constructor c = proxyClass.getConstructor(MyInvocationHandler.class);
            f.delete();
            
            // 返回字节码重组以后的代理对象
            return c.newInstance(h);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public static String generateSrc(Class<?>[] interfaces){
        StringBuilder builder = new StringBuilder();
        builder.append(MyProxy.class.getPackage() + ";" + ln);
        builder.append("import " + interfaces[0].getName() + ";" + ln);
        builder.append("import java.lang.reflect.*;" + ln);
        builder.append("public class $Proxy0 implements " + interfaces[0].getName() + "{" + ln);
        builder.append("MyInvocationHandler h;" + ln);
        builder.append("public $Proxy0(MyInvocationHandler h) { " + ln);
        builder.append("this.h = h;" + ln);
        builder.append("}" + ln);
        for (Method m : interfaces[0].getMethods()){
            Class<?> [] params = m.getParameterTypes();
            StringBuffer paramNames = new StringBuffer();
            StringBuffer paramValues = new StringBuffer();
            StringBuffer paramClasses = new StringBuffer();
            for (int i = 0; i < params.length; i++) {
                Class clazz = params[i];
                String type = clazz.getName();
//                String paramName = toLowerFirstCase(clazz.getSimpleName());
                String paramName = "var" + i;
                paramNames.append(type + " " + paramName);
                paramValues.append(paramName);
                paramClasses.append(clazz.getName() + ".class");
                if (i > 0 && i < params.length - 1){
                    paramNames.append(",");
                    paramClasses.append(",");
                    paramValues.append(",");
                }
            }
            builder.append("public " + m.getReturnType().getName() + " " + m.getName() + "(" + paramNames.toString() + ") {" + ln);
            builder.append("try {" + ln);
            builder.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + m.getName() + "\", new Class[]{" + paramClasses.toString() + "});" + ln);
            builder.append((hasReturnValue(m.getReturnType()) ? "return " : "") + getCaseCode("this.h.invoke(this, m, new Object[]{" + paramValues + "})", m.getReturnType()) + ";" + ln);
            builder.append("}catch(Error _ex){}");
            builder.append("catch(Throwable e){" + ln);
            builder.append("throw new UndeclaredThrowableException(e);" + ln);
            builder.append("}");
            builder.append(getReturnEmptyCode(m.getReturnType()));
            builder.append("}");
        }
        builder.append("}" + ln);
        return builder.toString();
    }

    // 类型转换Mappings
    private static Map<Class, Class> mappings = new HashMap<>();
    static {
        mappings.put(int.class, Integer.class);
    }

    // 返回值
    public static String getReturnEmptyCode(Class<?> returnClass){
        if (mappings.containsKey(returnClass)) return "return 0;";
        else if (returnClass == void.class) return "";
        else return "return null;";
    }

    // 类型转换
    public static String getCaseCode(String code, Class<?> returnClass) {
        // getName() 带有包名
        // getSimpleName() 不带包名
        // ((java.lang.Integer)100).intValue()
//        if (mappings.containsKey(returnClass)) return "((" + mappings.get(returnClass).getName() + ")" + code + ")." + returnClass.getSimpleName() + "Value()";
        return "(" + returnClass.getSimpleName() + ")" + code;
//        return code;
    }

    // 是否有返回值
    private static boolean hasReturnValue(Class<?> clazz){
        return clazz != void.class;
    }

    // 首字母大写
    private static String toLowerFirstCase(String src){
        char[] chars = src.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }
}

// MyClassLoader
class MyClassLoader extends ClassLoader{
    private File classPathFile;
    public MyClassLoader(){
        // 获取当前Class的根目录
        String classPath = MyClassLoader.class.getResource("").getPath();
        this.classPathFile = new File(classPath);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 当前class包名.类名
        String className = MyClassLoader.class.getPackage().getName() + "." + name;
        if (classPathFile != null){
            File classFile = new File(classPathFile, name.replaceAll("\\.", "/") + ".class");
            if (classFile.exists()){
                FileInputStream in = null;
                ByteArrayOutputStream out = null;
                try{
                    in = new FileInputStream(classFile);
                    out = new ByteArrayOutputStream();
                    byte[] buff = new byte[1024];
                    int len;
                    while((len = in.read(buff)) != -1){
                        out.write(buff, 0, len);
                    }
                    // 在运行时刻从文件中调入Class
                    // 如果java.lang.NoClassDefFoundError SDKs中加入tools.jar(jdk1.8/lib)
                    return defineClass(className, out.toByteArray(),0,out.size());
                }catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
}

// 放在这会class test.$Proxy0 cannot access its superinterface test.Person(public)
//interface Person{
//    String sayHi(String name);
//}

class PersonProxy implements MyInvocationHandler{
    private Person target;

    public Person getInstance(Person person){
        this.target = person;
        Class<?> clazz = target.getClass();
        return (Person) MyProxy.newProxyInstance(new MyClassLoader(), clazz.getInterfaces(), this);
    }

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

class FunctionTest{
    public static void main(String[] args) throws IOException {
        Person person = new PersonProxy().getInstance(new Person() {
            @Override
            public String sayHi(String name) {
                System.out.println("hello " + name);
                return name;
            }
        });
        System.out.println(person.sayHi("me"));
    }
}
// 可以手动删除生成文件

Proxy源码梳理

  • jdk8
  • 返回代理对象
public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
// Class
Class<?> cl = getProxyClass0(loader, intfs);
// 构造器
final Constructor<?> cons = cl.getConstructor(constructorParams);
// 实例
return cons.newInstance(new Object[]{h});
  • 生成Class
private static Class<?> getProxyClass0(ClassLoader loader,
                                       Class<?>... interfaces) {
    if (interfaces.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");
    }

    // If the proxy class defined by the given loader implementing
    // the given interfaces exists, this will simply return the cached copy;
    // otherwise, it will create the proxy class via the ProxyClassFactory
    return proxyClassCache.get(loader, interfaces);
}
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
    proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
  • proxyClassCache.get

  • 如果代理类已经被类加载器缓存过,则直接复制一个返回,否则会通过ProxyClassFactory来创建代理

public V get(K key, P parameter) {
    Objects.requireNonNull(parameter);

    expungeStaleEntries();

    Object cacheKey = CacheKey.valueOf(key, refQueue);

    // lazily install the 2nd level valuesMap for the particular cacheKey
    ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
    if (valuesMap == null) {
        ConcurrentMap<Object, Supplier<V>> oldValuesMap
            = map.putIfAbsent(cacheKey,
                              valuesMap = new ConcurrentHashMap<>());
        if (oldValuesMap != null) {
            valuesMap = oldValuesMap;
        }
    }

    // create subKey and retrieve the possible Supplier<V> stored by that
    // subKey from valuesMap
    Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
    Supplier<V> supplier = valuesMap.get(subKey);
    Factory factory = null;

    while (true) {
    	// 如果有supplier返回对应的class二进制文件
        if (supplier != null) {
            // supplier might be a Factory or a CacheValue<V> instance
            V value = supplier.get();
            if (value != null) {
                return value;
            }
        }
        // else no supplier in cache
        // or a supplier that returned null (could be a cleared CacheValue
        // or a Factory that wasn't successful in installing the CacheValue)

        // lazily construct a Factory
        // 创建工厂
        if (factory == null) {
            factory = new Factory(key, parameter, subKey, valuesMap);
        }

        if (supplier == null) {
            supplier = valuesMap.putIfAbsent(subKey, factory);
            if (supplier == null) {
                // successfully installed Factory
                supplier = factory;
            }
            // else retry with winning supplier
        } else {
            if (valuesMap.replace(subKey, supplier, factory)) {
                // successfully replaced
                // cleared CacheEntry / unsuccessful Factory
                // with our Factory
                // 所以导致 supplier.get()可能是在读缓存, 可能是在获取数据
                supplier = factory;
            } else {
                // retry with current supplier
                supplier = valuesMap.get(subKey);
            }
        }
    }
}

private final class Factory implements Supplier<V> {
@Override
public synchronized V get() {
// valueFactory为Proxy中的ProxyClassFactory
// apply为创建class文件
value = Objects.requireNonNull(valueFactory.apply(key, parameter));    
  • 生成二进制文件
private static final class ProxyClassFactory
    implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
  • ProxyGenerator.generateProxyClass
public static byte[] generateProxyClass(final String name,
                                        Class<?>[] interfaces,
                                        int accessFlags)
{
    ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
    // 二进制文件的方法
    final byte[] classFile = gen.generateClassFile();
	// 是否保存在本地
    if (saveGeneratedFiles) {

还有其他的代理,如cglib

由于本人理解能力有限,如有错误,请指出

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值