代理模式之动态代理
参考1:https://segmentfault.com/a/1190000009235245
参考2:https://blog.csdn.net/briblue/article/details/73928350
1、特点
(1) 在运行期,通过反射机制创建一个实现了一组给定接口的新类。
(2) 在运行时生成的class,必须提供一组interface给它,然后该class就宣称它实现了这些 interface。该class的实例可以当作这些interface中的任何一个来用。但是这个Dynamic Proxy其实就是一个Proxy, 它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
(3) 动态代理也叫做:JDK代理,接口代理。
(4) 接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强。
2、JDK中生成代理对象的API
(1)JDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是:
static Object newProxyInstance(ClassLoader loader, Class [] interfaces, InvocationHandler handler)
该方法是在Proxy类中是静态方法,且接收的三个参数依次为:
-
ClassLoader loader:指定当前目标对象使用类加载器,用null表示默认类加载器
-
Class [] interfaces:需要实现的接口数组
-
InvocationHandler handler:调用处理器,执行目标对象的方法时,会触发调用处理器的方法,从而把当前执行目标对象的方法作为参数传入
(2)java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
- invoke方法参数详解:
- proxy 代理对象
- method 代理对象调用的方法
- args 调用的方法中的参数
Proxy 动态产生的代理会调用 InvocationHandler 实现类,所以 InvocationHandler 是实际执行者。
3、代码演示
public static void main(String[] args) {
RealMovie realmovie = new RealMovie();
InvocationHandler movie = new Cinema(realmovie);
Movie m = (Movie)Proxy.newProxyInstance(RealMovie.class.getClassLoader(), RealMovie.class.getInterfaces(), movie);
m.play();
}
interface Movie {
void play();
}
class RealMovie implements Movie {
@Override
public void play() {
System.out.println("《哪吒·魔童降世》放映中......");
}
}
class Cinema implements InvocationHandler {
private Object type;
public Cinema(Object type) {
this.type = type;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("电影马上开始了,请保持环境卫生,文明观影!");
method.invoke(type, args);
System.out.println("电影马上结束了,请带好您的随身物品,欢迎下次光临!");
return null;
}
}
打印结果
4、总结
- 代理分为静态代理和动态代理两种。
- 静态代理,代理类需要自己编写代码写成。
- 动态代理,代理类通过 Proxy.newInstance() 方法生成。
- 不管是静态代理还是动态代理,代理与被代理者都要实现两样接口,它们的实质是面向接口编程。
- 静态代理和动态代理的区别是在于要不要开发者自己定义 Proxy 类。
- 动态代理通过 Proxy 动态生成 proxy class,但是它也指定了一个 InvocationHandler 的实现类。
- 代理模式本质上的目的是为了增强现有代码的功能。