1、代码
public interface Invoker {
public Object invoke(Invocation invocation);
}
public class EchoHandler implements Invoker {
@Override
public Object invoke(Invocation invocation) {
return invocation;
}
}
package com.wenc.common.ioc;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class BeanFactory implements InvocationHandler {
private static BeanFactory instance;
private Object proxiedObj;
private BeanFactory(){}
public static BeanFactory getInstance() {
if(instance != null) {
return instance;
}
synchronized(BeanFactory.class) {
if(instance == null) {
instance = new BeanFactory();
}
return instance;
}
}
public Object getBean(Object obj) {
this.proxiedObj = obj;
Class[] interfaces = obj.getClass().getInterfaces();
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), interfaces, this);
}
@Override
public Object invoke(Object paramObject, Method paramMethod, Object[] paramArrayOfObject) throws Throwable {
System.out.println("proxy invoked");
//return paramMethod.invoke(this.proxiedObj, paramArrayOfObject);//不会死循环,调用被代理类this.proxiedObj的方法后返回
return paramMethod.invoke(paramObject, paramArrayOfObject);//死循环,调用代理类$Proxy0.java的方法时,会再递归调用自己,造成死循环,详见后续$Proxy0.java代码
}
}
import com.wenc.common.ioc.BeanFactory;
import com.wenc.common.ioc.Invocation;
import com.wenc.common.ioc.Invoker;
public class Main {
public static void main(String[] args) {
Invoker echoHandler = new EchoHandler();
Invoker echoHandlerProxy = (Invoker) BeanFactory.getInstance().getBean(echoHandler);
Invocation invocation = new Invocation();
invocation.setId("100");
System.out.println(echoHandlerProxy.invoke(invocation));
}
}
2、死循环现象
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
3、原因分析过程
3.1 在jvm启动时加上-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true参数,保存生成的动态代理类字节码$Proxy0.class
3.2 反编译工具查看$Proxy0.class源码,如下:
package com.sun.proxy;
import com.wenc.common.ioc.Invocation;
import com.wenc.common.ioc.Invoker;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements Invoker {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(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 Object invoke(Invocation paramInvocation) {
try {
return this.h.invoke(this, m3, new Object[] { paramInvocation });
} 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") });
m3 = Class.forName("com.wenc.common.ioc.Invoker").getMethod("invoke", new Class[] { Class.forName("com.wenc.common.ioc.Invocation") });
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());
}
}
}
注意其中以下代码段:
public final Object invoke(Invocation paramInvocation) {
try {
return this.h.invoke(this, m3, new Object[] { paramInvocation });
} catch (Error|RuntimeException error) {
throw null;
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
由此可知死循环调用路径为:Main.main内echoHandlerProxy.invoke(invocation) (echoHandlerProxy即动态生成的$Proxy0类实例)-->$Proxy0.invoke方法内this.h.invoke(this, m3, new Object[] { paramInvocation }) -->BeanFactory.invoke方法内paramMethod.invoke(paramObject, paramArrayOfObject) -->$Proxy0.invoke方法内this.h.invoke(this, m3, new Object[] { paramInvocation }) -->BeanFactory.invoke方法内paramMethod.invoke(paramObject, paramArrayOfObject) -->....
4、解决
invoke方法内传入被代理类实例,避免死循环: