Java动态代理实现原理浅析
2016-05-06 09:55
429 查看
代码编写
接口编写public interface TargetInterface { void targetMethod(); }
实现类编写
public class Target implements TargetInterface { @Override public void targetMethod() { System.out.println("target method invoking ..."); } }
增强类编写
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; } }
测试类编写
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:
Proxy.getProxyClass0private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) { ... // Proxy类中维护了一个WeakCache对象,用于缓存动态生成的类,WeakCache.get方法不仅执行查找操作,当对象不存在时也会执行生成操作,下面来看下该方法的源码 return proxyClassCache.get(loader, interfaces); }
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 { ... } } } }
此方法会不断的循环以及重复判断,均是在考虑线程安全问题。此处未做深究。
Faotory.get
public synchronized V get() { ... try { //实现生成代理类对象,此方法在内部类ProxyClassFactory中实现 value = Objects.requireNonNull(valueFactory.apply(key, parameter)); } finally { ... } ... return value; }
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, 946c 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技术来实现的。
相关文章推荐
- java多线程总结
- Java中可变长参数的使用及注意事项
- 当js运行在java上,会有那些令人惊喜的表现呢!
- java如何在项目依赖的jar包中查找冲突的类
- JAVA中int、String的类型转换
- [Weblogic]startWebLogic.cmd配置JAVA_OPTIONS无效的解决思路与方案
- 解决eclipse的 Invalid project description. overlaps the location of another project: 问题
- 举例讲解设计模式中的访问者模式在Java编程中的运用
- java环境变量配置。
- eclipse中maven环境部署以及使用
- java中>> 和 >>>的区别
- Hbase创建表报错:ERROR: java.io.IOException: Table Namespace Manager not ready yet, try again later
- 【行为型模式】状态模式(state)之23种java设计模式
- java接口可以多继承
- Spring MVC的基础知识
- Java 格式化输出
- Android NDK报错(Eclipse)及解决方法
- ssh hibernate struts spring 工作原理及为什么要用
- float转16进制, 16进制转float(java )
- Eclipse批量修改包名