动态代理
动态代理与静态代理的区别:
- 静态代理,在程序运行前代理类 (.class)就已经存在了
- 动态代理,在程序运行时自动生成的代理类(.class)
静态代理地址:https://www.jianshu.com/p/75b3847cca5a
我们需要代理的东西多了,比如“卖烟”、“卖酒”、“卖房子”,每一个需要被代理的的对象都需要对应一个代理者,这样肯定是不太友好的,所以才有了动态代理
动态代理需要java.lang.reflect
包下的 Proxy
还是需要一个接口
/**
* 售卖接口
*/
public interface SellInterface {
void sell();
}
被代理类
/**
* 奔驰品牌,被代理的对象
*/
public class BMwBrand implements SellInterface {
@Override
public void sell() {
System.out.println("奔驰卖出了一件商品");
}
}
动态代理:如下
Proxy.newProxyInstance ()有三个参数:
- 被代理对象的ClassLoader
- 被代理对象实现的接口数组
- InvocationHandler 调用处理器,指的是被调用对象 的那个 方法被调用的时候 怎么去处理
BMWBrand brand = new BMWBrand();
SellInterface sellInterface = (SellInterface) Proxy.newProxyInstance(BMWBrand.class.getClassLoader(),
new Class[]{SellInterface.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("销售员拿提成");
Object obj = method.invoke(brand, args);
System.out.println("销售员提成");
return obj;
}
});
sellInterface.sell();
输出:
销售员加价
奔驰卖出了一件商品
销售员拿提成
代码都能看懂,但是为什么
sellInterface.sell()
会调用到InvocationHandler
的invoke方法?
想要了解这个需要加入下面这一行代码,jdk 版本低添加第一个,版本高就添加第二个
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
或者
System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");
加入之后会生成 $Proxy0.class
,这个class就是动态生成的代理类

$Proxy0.class
代码如下
public final class $Proxy0 extends Proxy implements SellInterface {
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 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 void sell() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
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("proxy.study_02.SellInterface").getMethod("sell");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
可以看到这个Class文件继承了Proxy
并实现了我们的SellInterface
,所以当我们调sellInterface.sell();
时就是调用的$Proxy0.class
中的sell()
方法
我们可以按住ctrl点击一下$Proxy0中的sell()
这个方法,就会跳转到我们调用的地方
SellInterface sellInterface = (SellInterface) Proxy.newProxyInstance(bmwBrand.getClass().getClassLoader(), new Class[]{SellInterface.class}, new MyInvocationHandler(bmwBrand));
sellInterface.sell(); //当我们调用这一行代码时其实就是调用的 $Proxy0.class 中的sell() 方法
再来看一下 代理类 中的 sell()
方法

这里的sell方法是调用了父类(
Proxy
)中成员变量h
的 invoke
方法
这个h
是哪来的呢,就是我的调用Proxy.newProxyInstance()
方法时传入的第三个参数InvocationHandler
,所以就会调用到他的invoke()
方法
网友评论