直接上代码:
public interface ShoppingService {
void shopping();
}
被代理类:
public class ShoppingServiceImpl implements ShoppingService {
@Override
public void shopping() {
System.out.println("shopping……");
}
}
public class MyHandler implements InvocationHandler {
private Object target;
MyHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("shopping")){
System.out.println("before shoping……");
Object result = method.invoke(target,args);
System.out.println("after shopping");
return result;
}
return method.invoke(target,args);
}
}
**Object result = method.invoke(target,args);**这个到后面应该就看得懂了。
public class Client {
public static void main(String[] args) {
ShoppingServiceImpl shoppingServiceImpl = new ShoppingServiceImpl();
// 保存代理类的字节码
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
ShoppingService proxy = (ShoppingService) Proxy.newProxyInstance(Client.class.getClassLoader(),shoppingServiceImpl.getClass().getInterfaces(),new MyHandler(shoppingServiceImpl));
proxy.shopping();
}
}
运行结果:
探究 Proxy.newProxyInstance方法:
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
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;
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
上面的代码被我删减了,主要看这几个:
在 checkProxyAccess方法中,进行参数验证在getProxyClass0方法中,生成代理类Class或者从proxyClassCache中找已生成过的代理类。通过getConstructor方法,获取生成的代理类的构造方法。通过newInstance方法,生成实例对象,也就是最终的代理对象==$Proxy0==。
代理类:
public final class $Proxy0 extends Proxy implements ShoppingService {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final void shopping() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.blue.proxy.ShoppingService").getMethod("shopping");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
}
}
}
上面代码被我删了很多,主要看shopping方法,里面的super.h.invoke(this, m3, (Object[])null) 去到了父类InvocationHandler,父类的invoke方法早就被MyHandler重写了。
本人理解有限,只是介绍了一个简单的流程。



