代理模式:
代理模式的主要作用有两点:
1. 因为某些原因一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
Q: 何为“不想或者不能直接引用另一个对象”?
A: 如果执行某个操作需要进行远程调用网络另一端的计算机,如果不使用代理模式,则需要将复杂的网络通信部分硬编码入客户端。为了简化客户端的行为,可以使用代理模式,由客户端通过代理对象向远程的计算机发出指令,网络通信部分则有代理对象完成。
2. 在代理对象调用被代理对象的方法前后,可以附加一些额外的操作(如对数据加密)。
代理模式一般涉及到的角色:
1. 抽象角色
抽象角色implements by代理类和被代理类,即为后两者的公共接口。
2. 代理角色
代理角色含有对真实角色的引用,从而可以操作真实对象,除此之外代理角色可以在执行真实角色操作时,附加其额外相当于对真实角色进行封装。
3. 真实角色
真实角色也就是被代理的角色,是客户最终向要调用的角色。
由于代理角色和真实角色同时实现了公共的接口,因此在客户看来,对代理角色的操作与对真实的角色的操作并无差别。
动态代理:
1. 通俗的说法:在编译阶段代理对象并不知道自己要去调用哪个被代理对象的方法。
2. 动态代理是程序在运行时动态的加载代理对象(根据所要代理对象的不同动态加载),动态的调用被代理类的方法。
Java动态代理的主要过程(同时参见以下代码):
核心方法:Proxy类的静态方法newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)
InvocationHandler接口,子类需重写invoke(Object proxy, Method method, Object[] args)方法
proxy:the proxy instance that the method was invoked on. 一般是指代理类
method:被代理的方法(通过java反射获得),args方法的参数。
loader 类装载器,与JVM类父委托加载机制有关。
interfaces 是真实类所拥有的全部接口的数组。
3 | * 抽象角色类:被代理对象与代理对象的公共接口 |
5 | public interface Base { |
7 | abstract public void doMethod(); |
05 | public class Target1 implements Base { |
08 | public void doMethod() { |
09 | System.out.println("Target1 Method has been invoked"); |
05 | public class Target2 implements Base { |
08 | public void doMethod() { |
09 | System.out.println("Target2 Method has been invoked"); |
03 | * 该代理类的内部属性为Object类,实际使用时通过该类的构造函数MyHandler(Object obj)对其赋值; |
04 | * 此外,在该类还实现了invoke方法,该方法中的 method.invoke(sub,args); |
05 | * 其实就是调用被代理对象的将要被执行的方法,方法参数sub是实际的被代理对象, |
06 | * args为执行被代理对象相应操作所需的参数。 |
07 | * 通过动态代理类,我们可以在调用之前或之后执行一些相关操作 |
09 | import java.lang.reflect.InvocationHandler; |
10 | import java.lang.reflect.Method; |
12 | public class MyHandler implements InvocationHandler { |
18 | public MyHandler(Object obj) { |
23 | public Object invoke(Object proxy, Method method, Object[] args) |
25 | System.out.println("before doMethod"); |
26 | method.invoke(obj, args); |
27 | System.out.println("after doMethod"); |
05 | import java.lang.reflect.InvocationHandler; |
06 | import java.lang.reflect.Proxy; |
09 | public static void main(String[] args) { |
10 | Target1 target1 = new Target1(); // 显示指定被代理类Target1 |
11 | InvocationHandler h1 = new MyHandler(target1); |
12 | Class<?> cls1 = target1.getClass(); |
13 | Base base1 = (Base) Proxy.newProxyInstance(cls1.getClassLoader(), |
14 | cls1.getInterfaces(), h1); |
17 | Target2 target2 = new Target2(); // 显示指定被代理类Target2 |
18 | InvocationHandler h2 = new MyHandler(target2); |
19 | Class<?> cls2 = target2.getClass(); |
20 | Base base2 = (Base) Proxy.newProxyInstance(cls2.getClassLoader(), |
21 | cls2.getInterfaces(), h2); |