Java动态代理实现原理浅析

代码编写

  1. 接口编写
    public interface TargetInterface {
    void targetMethod();
    }
  2. 实现类编写
    public class Target implements TargetInterface {
    @Override
    public void targetMethod() {
    System.out.println("target method invoking ...");
    }
    }
  3. 增强类编写
    public class ProxyHandler implements InvocationHandler {
    private Object proxyTarget;
    public ProxyHandler(Object proxyTarget) {
    this.proxyTarget = proxyTarget;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("do somethings before target method invoke");
    Object result = method.invoke(proxyTarget, args);
    System.out.println("do somethings after target method invoke");
    return result;
    }
    }
  4. 测试类编写
    public class ProxyTest {
    public static void main(String[] args) {
    System.out.println(Thread.currentThread().getContextClassLoader());
    TargetInterface target = new Target();
    ClassLoader loader = target.getClass().getClassLoader();
    Class<?>[] interfaces = target.getClass().getInterfaces();
    InvocationHandler proxyHandler = new ProxyHandler(target);
    TargetInterface proxyTarget = (TargetInterface) Proxy.newProxyInstance(loader, interfaces, proxyHandler);
    proxyTarget.targetMethod();
    }
    }

源码分析(源码篇幅过多,省略部分由“…”表示)

代码中proxyTarget增强类是由Proxy.newProxyInstance(…)生成的,查看该方法源码:
``public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException{
...
// step1:从缓存中查找代理类,若未缓存则生成后缓存,否则直接从缓存中获取.
Class<?> cl = getProxyClass0(loader, intfs);
try {
...
//step2:反射生成代理类实例
return newInstance(cons, ih);
...
} catch (NoSuchMethodException e) {
...
}
}

代码中可以看出,代理类的生成主要分为两步:
- 生成代理类
- 反射生成代理类实例

step1:
  1. Proxy.getProxyClass0
    private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {
    ...
    // Proxy类中维护了一个WeakCache对象,用于缓存动态生成的类,WeakCache.get方法不仅执行查找操作,当对象不存在时也会执行生成操作,下面来看下该方法的源码
    return proxyClassCache.get(loader, interfaces);
    }
  2. WeakCache.get
    public V get(K key, P parameter) {
    ...
    while (true) {
    if (supplier != null) {
    //已从缓存中查找到对象,直接返回
    V value = supplier.get();
    if (value != null) {
    return value;
    }
    }
    if (factory == null) {
    //已从缓存中查找到对象,且调用该对象的get方法生成代理类后直接返回,get方法实现下文详述
    factory = new Factory(key, parameter, subKey, valuesMap);
    }
    if (supplier == null) {
    //将新生成的对象缓存
    supplier = valuesMap.putIfAbsent(subKey, factory);
    if (supplier == null) {
    supplier = factory;
    }
    } else {
    ...
    }
    }
    }
    }

    此方法会不断的循环以及重复判断,均是在考虑线程安全问题。此处未做深究。
  3. Faotory.get
    public synchronized V get() {
    ...
    try {
    //实现生成代理类对象,此方法在内部类ProxyClassFactory中实现
    value = Objects.requireNonNull(valueFactory.apply(key, parameter));
    } finally {
    ...
    }
    ...
    return value;
    }
  4. ProxyClassFactory.apply
    public Class apply(ClassLoader loader, Class[] interfaces) {
    //校验interfaces
    ...
    String proxyPkg = null;
    ...
    //生成packagename,默认为com.sun.proxy
    if (proxyPkg == null) {
    // if no non-public proxy interfaces, use package
    proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
    }
    //生成classname,采用AutomicLong自增方式
    long num = nextUniqueNumber.getAndIncrement();
    String proxyName = proxyPkg + proxyClassNamePrefix + num;
    // 生成字节码文件
    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
    proxyName, interfaces);
    // 调用native方法,加载生成的字节码文件,并返回代理类的引用
    try {
    return defineClass0(loader, proxyName,
    proxyClassFile, 0, proxyClassFile.length);
    } catch (ClassFormatError e) {
    ...
    }
    }

    将生成的proxyClassFile字节码写入到文件并反编译后,信息如下:

package com.sun.proxy.$Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import x.constant.proxy.TargetInterface;
public final class 1 extends Proxy implements TargetInterface {
private static Method m3;
private static Method m1;
private static Method m0;
private static Method m2;
public 1(InvocationHandler paramInvocationHandler) throws {
super(paramInvocationHandler);
}
public final void targetMethod() throws {
try {
this.h.invoke(this, m3, null);
return;
}catch (Error|RuntimeException localError) {
throw localError;
}catch (Throwable localThrowable){
throw new UndeclaredThrowableException(localThrowable);
}
}
public final boolean equals(Object paramObject) {
...
}
public final int hashCode() {
...
}
public final String toString() throws {
...
}
static {
try {
m3 = Class.forName("x.constant.proxy.TargetInterface").getMethod("targetMethod", new Class[0]);
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
return;
}catch (NoSuchMethodException localNoSuchMethodException){
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}

可以看到,该类位于com.sun.proxy.$Proxy包下,继承Proxy对象且实现我们自定义的TargetInterface接口;构造方法需要一个InvocationHandler对象做为参数;增强后的targetMethod方法会调用InvocationHandler对象的invoke方法。

step2

增强后的类信息已经加载到JVM中并得到了该类的引用,通过反射机制调用该类的构造方法并传入我们自定义的InvocationHandler对象做为参数,即可生成该代理类对象,此处不再做解析。

通过源代码的阅读可以发现,java动态代理的实现过程:
1. 根据Interface动态生成一个该接口的代理类,并通过调用InvocationHandler中的invoke方法的方式来实现Interface中定义的方法
2. 动态加载该代理类,并通过反射的方式获取该代理类的对象。
归根结底,其实现也是通过字节码生成ASM技术来实现的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值