IT徐胖子原创本文未授权请勿转载
1 文章概述
Dubbo源码里有很多动态代理使用场景,例如源码里JdkProxyFactory正是使用了JDK动态代理。
package org.apache.dubbo.rpc.proxy.jdk;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class JdkProxyFactory extends AbstractProxyFactory {@Overridepublic <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));}@Overridepublic <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {return new AbstractProxyInvoker<T>(proxy, type, url) {@Overrideprotected Object doInvoke(T proxy, String methodName,Class<?>[] parameterTypes,Object[] arguments) throws Throwable {Method method = proxy.getClass().getMethod(methodName, parameterTypes);return method.invoke(proxy, arguments);}};}}
本文我们介绍JDK动态代理实现原理,后续文章再进行Dubbo源码分析。下面我们通过一个实例分析JDK动态代理实现原理。
2 代码实例
2.1 业务接口
public interface StudentJDKService {public void addStudent();public void updateStudent();}public class StudentJDKServiceImpl implements StudentJDKService {@Overridepublic void addStudent() {System.out.println("add student");}@Overridepublic void updateStudent() {System.out.println("update student");}}
2.2 InvocationHander
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class TransactionHandler implements InvocationHandler {// 被代理对象private Object target;// 构造函数public TransactionHandler(Object target) {this.target = target;}// 代理逻辑@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("transaction begin");Object result = method.invoke(target, args);System.out.println("transaction end");return result;}}
2.3 测试用例
public class TestStudentService {public static void main(String[] args) throws Exception {StudentJDKService target = new StudentJDKServiceImpl();TransactionHandler handler = new TransactionHandler(target);ClassLoader loader = target.getClass().getClassLoader();Class<?>[] interfaces = target.getClass().getInterfaces();StudentJDKService proxy = (StudentJDKService) Proxy.newProxyInstance(loader, interfaces, handler);System.out.println(proxy.getClass().getName());proxy.addStudent();}}// 输出结果// com.sun.proxy.$Proxy0// transaction begin// add student// transaction end
3 源码分析
3.1 分析入口
StudentJDKService proxy = (StudentJDKService) Proxy.newProxyInstance(loader, interfaces, handler);
3.2 Proxy
public class Proxy implements java.io.Serializable {private static final Class<?>[] constructorParams = { InvocationHandler.class };protected InvocationHandler h;@CallerSensitivepublic static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {// InvocationHandler不能为空Objects.requireNonNull(h);final Class<?>[] intfs = interfaces.clone();final SecurityManager sm = System.getSecurityManager();if (sm != null) {checkProxyAccess(Reflection.getCallerClass(), loader, intfs);}// 获取指定代理类Class<?> cl = getProxyClass0(loader, intfs);try {// 权限校验if (sm != null) {checkNewProxyPermission(Reflection.getCallerClass(), cl);}// 获取代理类的构造器final Constructor<?> cons = cl.getConstructor(constructorParams);final InvocationHandler ih = h;if (!Modifier.isPublic(cl.getModifiers())) {AccessController.doPrivileged(new PrivilegedAction<Void>() {public Void run() {cons.setAccessible(true);return null;}});}// 通过代理类构造器实例化为代理对象return cons.newInstance(new Object[] {h});}}}
3.3 getProxyClass0
public class Proxy implements java.io.Serializable {// 代理类缓存// 如果缓存里不存则通过ProxyClassFactory生成代理类private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) {if (interfaces.length > 65535) {throw new IllegalArgumentException("interface limit exceeded");}return proxyClassCache.get(loader, interfaces);}}
3.4 ProxyClassFactory
private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> {// 类名前缀private static final String proxyClassNamePrefix = "$Proxy";// 代理类序号private static final AtomicLong nextUniqueNumber = new AtomicLong();@Overridepublic Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);// 遍历接口数组for (Class<?> intf : interfaces) {Class<?> interfaceClass = null;try {interfaceClass = Class.forName(intf.getName(), false, loader);} catch (ClassNotFoundException e) {}if (interfaceClass != intf) {throw new IllegalArgumentException(intf + " is not visible from class loader");}// 校验是否是接口if(!interfaceClass.isInterface()) {throw new IllegalArgumentException(interfaceClass.getName() + " is not an interface");}// 接口去重if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {throw new IllegalArgumentException("repeated interface: " + interfaceClass.getName());}}// 代理类所在的包路径String proxyPkg = null;// 代理类的访问修饰符int accessFlags = Modifier.PUBLIC | Modifier.FINAL;for (Class<?> intf : interfaces) {int flags = intf.getModifiers();if (!Modifier.isPublic(flags)) {accessFlags = Modifier.FINAL;String name = intf.getName();int n = name.lastIndexOf('.');String pkg = ((n == -1) ? "" : name.substring(0, n + 1));if (proxyPkg == null) {proxyPkg = pkg;} else if (!pkg.equals(proxyPkg)) {throw new IllegalArgumentException("non-public interfaces from different packages");}}}if (proxyPkg == null) {proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";}// 生成代理类名long num = nextUniqueNumber.getAndIncrement();String proxyName = proxyPkg + proxyClassNamePrefix + num;// 核心方法生成代理类字节码byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);try {// 通过本地方法defineClass0生成代理return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);} catch (ClassFormatError e) {throw new IllegalArgumentException(e.toString());}}}
4 代理类字节码分析
通过分析源码我们知道ProxyGenerator生成了代理类字节码,这是动态代理的核心。下面我们直接调用这个方法看看生成字节码的具体内容。
public class TestStudentService {public static void main(String[] args) throws Exception {createProxyClassFile();}public static void createProxyClassFile() {String name = "Student$Proxy";byte[] data = ProxyGenerator.generateProxyClass(name, new Class[] { StudentJDKService.class });FileOutputStream out = null;try {// 字节码文件路径String fileName = "c:/test/" + name + ".class";File file = new File(fileName);out = new FileOutputStream(file);out.write(data);} catch (Exception e) {System.out.println(e.getMessage());} finally {if (null != out) {try {out.close();} catch (IOException e) {e.printStackTrace();}}}System.out.println();}}
找到代理类文件通过反编译工具打开得到如下代码,通过代码我们就可以看到动态代理实现原理。
import com.itxpz.dubbo.spi.proxy.jdk.StudentJDKService;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class Student$Proxy extends Proxy implements StudentJDKService {private static Method m1;private static Method m4;private static Method m3;private static Method m2;private static Method m0;public Student$Proxy(InvocationHandler paramInvocationHandler) {super(paramInvocationHandler);}public final boolean equals(Object paramObject) {try {return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();} catch (Error | RuntimeException error) {throw null;} catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}public final void updateStudent() {try {// invocationHandler.invokethis.h.invoke(this, m4, null);return;} catch (Error | RuntimeException error) {throw null;} catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}public final void addStudent() {try {// invocationHandler.invokethis.h.invoke(this, m3, null);return;} catch (Error | RuntimeException error) {throw null;} catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}public final String toString() {try {return (String)this.h.invoke(this, m2, null);} catch (Error | RuntimeException error) {throw null;} catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}public final int hashCode() {try {return ((Integer)this.h.invoke(this, m0, null)).intValue();} catch (Error | RuntimeException error) {throw null;} catch (Throwable throwable) {throw new UndeclaredThrowableException(throwable);}}static {try {m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });m4 = Class.forName("com.itxpz.dubbo.proxy.jdk.StudentJDKService").getMethod("updateStudent", new Class[0]);m3 = Class.forName("com.itxpz.dubbo.proxy.jdk.StudentJDKService").getMethod("addStudent", new Class[0]);m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);return;} catch (NoSuchMethodException noSuchMethodException) {throw new NoSuchMethodError(noSuchMethodException.getMessage());} catch (ClassNotFoundException classNotFoundException) {throw new NoClassDefFoundError(classNotFoundException.getMessage());}}}
5 文章总结
本文我们介绍了JDK动态代理实现原理,后续文章再进行Dubbo源码分析,到时候会看到大量使用动态代理的场景。
长按二维码关注更多精彩文章
文章转载自JAVA前线,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




