静态代理
代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。
public interface Movie {
void play();
}
真正的实现类
public class RealMovie implements Movie {
@Override
public void play() {
// TODO Auto-generated method stub
System.out.println("您正在观看电影 《肖申克的救赎》");
}
}
静态代理 对movie进行代理
public class Cinema implements Movie {
RealMovie movie;
public Cinema(RealMovie movie) {
super();
this.movie = movie;
}
@Override
public void play() {
guanggao(true);
movie.play();
guanggao(false);
}
public void guanggao(boolean isStart){
if ( isStart ) {
System.out.println("电影马上开始了,爆米花、可乐、口香糖9.8折,快来买啊!");
} else {
System.out.println("电影马上结束了,爆米花、可乐、口香糖9.8折,买回家吃吧!");
}
}
}
public class ProxyTest {
public static void main(String[] args) {
RealMovie realmovie = new RealMovie();
Movie movie = new Cinema(realmovie);
movie.play();
}
}
动态代理
上面代码中 Cinema 类是代理,我们需要手动编写代码让 Cinema 实现 Movie 接口,而在动态代理中,我们可以让程序在运行的时候自动在内存中创建一个实现 Movie 接口的代理,而不需要去定义 Cinema 这个类。这就是它被称为动态的原因。
假设有一个大商场,商场有很多的柜台,有一个柜台卖茅台酒
//卖酒的许可证
public interface SellWine {
void mainJiu();
}
public class MaotaiJiu implements SellWine {
@Override
public void mainJiu() {
// TODO Auto-generated method stub
System.out.println("我卖得是茅台酒。");
}
}
public class GuitaiA implements InvocationHandler {
private Object pingpai;
public GuitaiA(Object pingpai) {
this.pingpai = pingpai;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("销售开始 柜台是: "+this.getClass().getSimpleName());
method.invoke(pingpai, args);
System.out.println("销售结束");
return null;
}
}
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
MaotaiJiu maotaijiu = new MaotaiJiu();
InvocationHandler jingxiao1 = new GuitaiA(maotaijiu);
SellWine dynamicProxy = (SellWine) Proxy.newProxyInstance(MaotaiJiu.class.getClassLoader(),
MaotaiJiu.class.getInterfaces(), jingxiao1);
dynamicProxy.mainJiu();
}
}
方法解析
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
loader 自然是类加载器,interfaces 代码要用来代理的接口,h 一个 InvocationHandler 对象
InvocationHandler
InvocationHandler 是一个接口,官方文档解释说,每个代理的实例都有一个与之关联的 InvocationHandler 实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类,由它决定处理。
因为,Proxy 动态产生的代理会调用 InvocationHandler 实现类,所以 InvocationHandler 是实际执行者。
红框中 $Proxy0 就是通过 Proxy 动态生成的。
$Proxy0 实现了要代理的接口。
$Proxy0 通过调用 InvocationHandler 来执行任务。
上一篇代理模式回顾:
https://www.jianshu.com/p/ed281dcf9fa7
参考文章:
https://blog.csdn.net/briblue/article/details/73928350