代理
一般是代理对象持有被代理对象,然后在代理对象中加一些额外的处理逻辑,然后在真实对象调用前后执行。
JDK动态代理
代理对象和被代理对象实现同一套接口,然后调用代理对象的方法,实际上执行代理对象添加的逻辑和被代理对象的逻辑。特殊说明:代理对象是动态生成的。
话不多说,直接上代码。对JDK动态代理比较熟的同学,可以略过前面几个类,重点看一下InvocationHandler的实现类(InvocationHandlerImpl)和代理生成的字节码($Proxy0),里面注释基本上都写了。
第一个接口类
package wz_ling.learning.proxy;
public interface PlayDemo {
void playGame(String game);
}
第二个接口类
package wz_ling.learning.proxy;
public interface SayDemo {
String sayGoodBye();
}
被代理对象(真实对象)
package wz_ling.learning.proxy;
public class RealObject implements SayDemo, PlayDemo {
@Override
public String sayGoodBye() {
return "goodbye RealObject";
}
@Override
public void playGame(String game) {
System.out.println("play game[" + game + "]");
}
}
InvocationHandler的实现类,实际持有被代理对象。
package wz_ling.learning.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class InvocationHandlerImpl implements InvocationHandler {
/**
* 被代理对象
*/
private Object realObject;
public InvocationHandlerImpl(Object realObject) {
this.realObject = realObject;
}
/**
* 1、重写InvocationHandler方法
* 2、代理的前后逻辑都是在重写invoke方法中实现
*
* @param proxy 被代理对象
* @param method 目标方法
* @param args 方法参数
* @return
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before proxy");
Object invoke = method.invoke(realObject, args);
System.out.println("after proxy");
return invoke;
}
}
ProxyDemo类
package wz_ling.learning.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class ProxyDemo {
public static void main(String[] args) {
//设置保存动态生成的class文件,在com.sun.proxy包下
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
//代理的真实对象
RealObject realSubject = new RealObject();
//代理逻辑织入的地方
InvocationHandler handler = new InvocationHandlerImpl(realSubject);
ClassLoader loader = realSubject.getClass().getClassLoader();
Class<?>[] interfaces = realSubject.getClass().getInterfaces();
Object proxy = Proxy.newProxyInstance(loader, interfaces, handler);
//以下演示了代理成不同的类型
SayDemo sayProxy = (SayDemo) proxy;
sayProxy.sayGoodBye();
PlayDemo playDemo = (PlayDemo) proxy;
playDemo.playGame("真~三国无双");
}
}
代理生成的字节码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sun.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import wz_ling.learning.proxy.PlayDemo;
import wz_ling.learning.proxy.SayDemo;
//代理类实现了和被代理对象一样的接口
//代理类继承了Proxy类
public final class $Proxy0 extends Proxy implements SayDemo, PlayDemo {
//在静态块中初始化了下面的几个Method(m1,m2,m3...)
//翻到最下面的静态块,可以看到m3、m4就是被代理对象实现的接口的方法
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m4;
private static Method m0;
//代理类在初始化时设置InvocationHandler(我们需要自己实现该接口,重写invoke方法,即上面的InvocationHandlerImpl的实现类)
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String sayGoodBye() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void playGame(String var1) throws {
try {
super.h.invoke(this, m4, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (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("wz_ling.learning.proxy.SayDemo").getMethod("sayGoodBye");
m4 = Class.forName("wz_ling.learning.proxy.PlayDemo").getMethod("playGame", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
关键代码:
Object proxy = Proxy.newProxyInstance(loader, interfaces, handler);
第一个参数,类加载器
第二个参数,接口列表
第三个参数,调用处理器,入参是InvocationHandler接口类,需要自己实现该类,重写该接口。
在看代理生成的字节码,继承了Proxy类,同时实现了入参接口列表中的所有接口,在看$Proxy0的构造器,入参就是上面的第3个参数,即我们自己实现的InvocationHandler接口类,最终调用了父类Proxy的有参构造器,所以最终代理类是持有InvocationHandler实现类,而实现类又持有了被代理类。
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
再看调用代码
SayDemo sayProxy = (SayDemo) proxy;
sayProxy.sayGoodBye();
实际执行的是代理类$Proxy0中的sayGoodBye()方法
public final String sayGoodBye() throws {
try {
//调用的是InvocationHandler的invoke方法,即我们自己重写的InvocationHandler的方法
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
所以,到这里也可以回到一个经典的问题,为什么JDK的动态代理必须实现接口而不能是继承被代理类?
两个方面:
1、从实现上来看,入参就需要接口列表,代理对象也实现同样的接口,如果没有接口,那么怎么调用呢?
2、代理类已经继承了Proxy类,java单继承。
1557

被折叠的 条评论
为什么被折叠?



