代理模式和java动态代理的机制(一)InvocationHandler
2011-07-26 15:51
756 查看
首先回顾下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);
}
}
抽象主题角色
public interface Subject{
public void doOperationOne();
}
实际主题角色
public class RealSubject implements Subject{
@Override
public void doOperationOne() {
System.out.println("One~~~~~~~~~~~~~~~~~~~~~~");
}
}
代理角色
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.....");
target.doOperationOne();
System.out.println("after.....");
}
}
动态代理
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();
InvocationHandler proxyImpl = new Handler(realSubject);
Subject proxy = (Subject) Proxy.newProxyInstance(
realSubject.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
proxyImpl );
return proxy;
}
}
原本代理角色的工作被移动到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
//
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println(method.getName() + " before...");
method.invoke(realSubject, args);
System.out.println(method.getName() + " after...");
return null;
}
}
研究下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
/*
* Look up or generate the designated proxy class.
*/
Class cl = getProxyClass(loader, interfaces);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
Constructor cons = cl.getConstructor(constructorParams);
return (Object) cons.newInstance(new Object[] { h });
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
} catch (IllegalAccessException e) {
throw new InternalError(e.toString());
} catch (InstantiationException e) {
throw new InternalError(e.toString());
} catch (InvocationTargetException e) {
throw new InternalError(e.toString());
}
}
第十九行:根据接口产生一个类(代理?)。
第二十行:获取代理类的构造器。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
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
红色标记出来的方法,无法看到源码。不过根据语义大致应该是自动产生一个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 }
@Override
public void doOperationOne() {
try {
Method method = Subject.class.getDeclaredMethod("doOperationOne");
System.out.println(method.getName());
handler.invoke(this, method,null);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
新的客户端,验证下。
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
public static Subject getASubject(){
RealSubject realSubject = new RealSubject();
InvocationHandler handler= new Handler(realSubject);
Subject subject = new Imagined(handler);
return subject;
}
}
待续...
相关文章推荐
- java动态代理模式Proxy之JDK动态代理机制
- Java 动态代理Proxy和Invacationhandler的使用
- Proxy模式及Java内建的动态代理机制
- 如何使用Proxy模式及Java内建的动态代理机制
- 如何使用Proxy模式及Java内建的动态代理机制
- Java程序员从笨鸟到菜鸟之(三十九)大话设计模式(七)代理模式和java动态代理机制
- 模拟实现Struts拦截器-蕴含着代理模式,AOP,工厂模式,依赖注入,Java 反射,动态构造等机制
- Java程序员从笨鸟到菜鸟之(三十九)大话设计模式(七)代理模式和java动态代理机制
- 如何使用Proxy模式及Java内建的动态代理机制
- 如何使用Proxy模式及Java内建的动态代理机制
- 如何使用Proxy模式及Java内建的动态代理机制 推荐
- 如何使用Proxy模式及Java内建的动态代理机制
- java动态代理模式之Cglib动态代理机制
- Java程序员从笨鸟到菜鸟之(三十九)大话设计模式(七)代理模式和java动态代理机制
- 设计模式(七)代理模式和java动态代理机制
- 代理设计模式之(静态代理+Java自身提供的动态代理机制)
- java 代理模式及动态代理机制深入分析
- 15. JAVA 反射机制 Part 2(动态代理、类的生命周期、工厂设计模式) ----- 学习笔记
- java设计模式(七)代理模式和java动态代理机制
- 设计模式-java实现动态代理