代理模式和java动态代理的机制(一)InvocationHandler
首先回顾下Proxy模式
Provide a surrogate or palceholder for another object to control access to it.
其实就是把要控制的类包上一层。接口是一致的,所以从外面看不出区别,里面却大有乾坤。
客户类:
1 public class ProxyTest2 {
2 public static void main(String[] args) {
3 Subject subject = ProxyTest2.getASubject();
4 subject.doOperationOne();
5 }
6
7 public static Subject getASubject(){
8 RealSubject realSubject = new RealSubject();
9 return new Proxy(realSubject);
10 }
11 }
抽象主题角色
1 public interface Subject{
2 public void doOperationOne();
3 }
实际主题角色
1 public class RealSubject implements Subject{
2
3 @Override
4 public void doOperationOne() {
5 System.out.println("One~~~~~~~~~~~~~~~~~~~~~~");
6
7 }
8 }
代理角色
1 public class Proxy implements Subject {
2 Subject target;
3 public Proxy(Subject target){
4 this.target = target;
5 }
6
7 @Override
8 public void doOperationOne() {
9 System.out.println("befer.....");
10 target.doOperationOne();
11 System.out.println("after.....");
12 }
13 }
动态代理
java提供一个机制,可以给任意接口的实例加上一个代理。叫做动态代理。
上面这个例子的抽象主题角色和 真实主题角色保留。看看动态代理是怎么做的。
新的客户端:
1 public class ProxyTest {
2
3 public static void main(String[] args) {
4 Subject subject = ProxyTest.getASubject();
5 subject.doOperationOne();
6 }
7
8 public static Subject getASubject(){
9 RealSubject realSubject = new RealSubject();
10 InvocationHandler proxyImpl = new Handler(realSubject);
11 Subject proxy = (Subject) Proxy.newProxyInstance(
12 realSubject.getClass().getClassLoader(),
13 realSubject.getClass().getInterfaces(),
14 proxyImpl );
15 return proxy;
16 }
17
18 }
原本代理角色的工作被移动到java.lang.reflect.InvocationHandler接口的实现里完成
1 public class Handler implements InvocationHandler {
2 Subject realSubject;
3
4 public Handler(Subject realSubject) {
5 this.realSubject = realSubject;
6 }
7
8 //
9
10 //
11 public Object invoke(Object proxy, Method method, Object[] args)
12 throws Throwable {
13 System.out.println(method.getName() + " before...");
14 method.invoke(realSubject, args);
15 System.out.println(method.getName() + " after...");
16 return null;
17 }
18 }
研究下reflect.Proxy的源码看看是怎么和InvocationHandler配合实现动态代理的效果
1 public static Object newProxyInstance(ClassLoader loader,
2 Class<?>[] interfaces,
3 InvocationHandler h)
4 throws IllegalArgumentException
5 {
6 if (h == null) {
7 throw new NullPointerException();
8 }
9
10 /*
11 * Look up or generate the designated proxy class.
12 */
13 Class cl = getProxyClass(loader, interfaces);
14
15 /*
16 * Invoke its constructor with the designated invocation handler.
17 */
18 try {
19 Constructor cons = cl.getConstructor(constructorParams);
20 return (Object) cons.newInstance(new Object[] { h });
21 } catch (NoSuchMethodException e) {
22 throw new InternalError(e.toString());
23 } catch (IllegalAccessException e) {
24 throw new InternalError(e.toString());
25 } catch (InstantiationException e) {
26 throw new InternalError(e.toString());
27 } catch (InvocationTargetException e) {
28 throw new InternalError(e.toString());
29 }
30 }
第十九行:根据接口产生一个类(代理?)。
第二十行:获取代理类的构造器。constructorParams是个final的Class数组 { InvocationHandler.class })
第二十一行:以传入的InvocationHandler实例为参数,实例化代理。返回。
下面看下用于生成代理类的getProxyCalss方法里核心的代码。
1 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
2 proxyName, interfaces);
3 try {
4 proxyClass = defineClass0(loader, proxyName,
5 proxyClassFile, 0, proxyClassFile.length);
6 } catch (ClassFormatError e) {
7 /*
8 * A ClassFormatError here means that (barring bugs in the
9 * proxy class generation code) there was some other
10 * invalid aspect of the arguments supplied to the proxy
11 * class creation (such as virtual machine limitations
12 * exceeded).
13 */
14 throw new IllegalArgumentException(e.toString());
15 }
16 }
红色标记出来的方法,无法看到源码。不过根据语义大致应该是自动产生一个class。
我们知道代理类实现的接口,知道代理类有一个InvocationHandler类型的成员。要生成这么一个代理类似乎也不太难。
1 import java.lang.reflect.InvocationHandler;
2 import java.lang.reflect.Method;
3
4 public class Imagined implements Subject {
5 private InvocationHandler handler;
6
7 public Imagined(InvocationHandler handler){
8 this.handler = handler;
9 }
10
11 @Override
12 public void doOperationOne() {
13 try {
14 Method method = Subject.class.getDeclaredMethod("doOperationOne");
15 System.out.println(method.getName());
16 handler.invoke(this, method,null);
17 } catch (Throwable e) {
18 e.printStackTrace();
19 }
20 }
21 }
新的客户端,验证下。
1 import java.lang.reflect.InvocationHandler;
2
3 public class ProxyTest3 {
4
5 public static void main(String[] args) {
6 Subject subject = ProxyTest3.getASubject();
7 subject.doOperationOne();
8 }
9
10 public static Subject getASubject(){
11 RealSubject realSubject = new RealSubject();
12 InvocationHandler handler= new Handler(realSubject);
13 Subject subject = new Imagined(handler);
14 return subject;
15 }
16
17 }
待续...
以上是 代理模式和java动态代理的机制(一)InvocationHandler 的全部内容, 来源链接: utcz.com/z/392385.html