java动态代理原理解析
DamInterface;
public void sayHello();
public int sayHelloa();
}
DamImpl;
public class DamImpl implements DamInterface {
public void sayHello() {
System.out.println("Hello");
}
@Override
public int sayHelloa() {
System.out.println("Helloa");
return 0;
}
}
DamInvocationHandler;
public class DamInvocationHandler implements InvocationHandler {
private Object target;
public DamInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
result = method.invoke(proxy, args);
return result;
}
public Object getProxy() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass()
.getInterfaces(), this);
}
}
ProxyMain;
public class ProxyMain {
public static void main(String[] args) {
DamInterface dam = new DamImpl();
DamInvocationHandler handler = new DamInvocationHandler(dam);
// 创建动态代理对象
DamInterface proxy = (DamInterface) handler.getProxy();
proxy.sayHello();
proxy.sayHelloa();
}
}
运行后返回
Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
at com.sun.proxy.$Proxy0.sayHello(Unknown Source)
at com.jd.o2o.proxy.ProxyMain.main(ProxyMain.java:12)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.jd.o2o.proxy.DamInvocationHandler.invoke(DamInvocationHandler.java:19)
... 2 more
程序貌似进入了死循环了!!!
采用笨办法 利用ProxyGenerator 生成代理class文件保存下来 反编译查看究竟是什么原因
DamInterface dam = new DamImpl();
byte[] generateProxyClass =
ProxyGenerator.generateProxyClass("Dam$1", dam.getClass().getInterfaces());
try {
File file = new File("d:/Dam$1.class");
FileOutputStream fos = new FileOutputStream(file);
fos.write(generateProxyClass);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
在系统d盘根目录下生成了一个Dam$1.class文件 反编译后如下
implements DamInterface
{
private static Method m4;
private static Method m1;
private static Method m3;
private static Method m0;
private static Method m2;
public final void sayHello()
throws
{
try
{
this.h.invoke(this, m4, null);
return;
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int sayHelloa()
throws
{
try
{
return ((Integer)this.h.invoke(this, m3, null)).intValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return ((String)this.h.invoke(this, m2, null));
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m4 = Class.forName("com.jd.o2o.proxy.DamInterface").getMethod("sayHello", new Class[0]);
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m3 = Class.forName("com.jd.o2o.proxy.DamInterface").getMethod("sayHelloa", new Class[0]);
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());
}
}
}
反编译后发现Proxy后的Dam采用调用接口Proxy中的InvocationHandler的invoke方法,我们采用自己的DamInvocationHandler 故调用我们的invoke方法,此时查看代码反射调用是的Proxy的sysHello方法,故进入反射的循环调用了,所以出现了我们看到的死循环的打印错误信息
因为我们创建的是代理对象,所以此时DamInvocationHandler 的invoke方法应该改为调用target对象,因为代理的只是接口,所以真正调用应该为调用target的实现
修改 DamInvocationHandler invoke方法为
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
result = method.invoke(target, args);
return result;
}
然后运行ProxyMain