您的位置:首页 > 编程语言 > Java开发

JDK中的动态代理之二

2007-12-06 15:01 232 查看
[align=center]JDK中的动态代理之二[/align]
[align=center][/align]
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)throws IllegalArgumentException{
if (h == null) { throw new NullPointerException(); } //InvocationHandler为null抛出异常
Class cl = getProxyClass(loader, interfaces); //使用上面的方法得到一个ProxyClass
try {
Constructor cons = cl.getConstructor(constructorParams); //得到此类的构造器
return (Object) cons.newInstance(new Object[] { h }); //使用Handler构造对象
} 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());
}
}
public static boolean isProxyClass(Class<?> cl) { //判断某个Class是否为ProxyClass
if (cl == null) { throw new NullPointerException(); } //输入为null抛出异常
return proxyClasses.containsKey(cl); //返回该Proxy的Chche中是否存在该Class
}
//得到某个ProxyClass对象对应的InvocationHandler
public static InvocationHandler getInvocationHandler(Object proxy)throws IllegalArgumentException{
if (!isProxyClass(proxy.getClass())) { //该对象不是ProxyClass则抛出异常
throw new IllegalArgumentException("not a proxy instance");
}
Proxy p = (Proxy) proxy; //是ProxyClass则downcast
return p.h; //返回此ProxyClass的成员变量
}
//到目前为止,我们可以猜测在创建ProxyClass时,
//肯定使用该Proxy类的子类或者其protected的构造器中的一种
private static native Class defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);
//使用JNI创建一个Class
}
上面使用多个Cache,以下是这些Cache的层次图:




四、使用动态代理的例子
下面给出一个具体的例子:
//ServiceIF.java
public interface ServiceIF {
public void doService();
}
以上是具体提供服务的对象的接口。下面给出其实现。
//Service.java
public class Service implements ServiceIF{
public void doService(){
System.out.println("正在执行您申请的服务!");
}
}
使用JDK中的动态代理时必须实现InvocationHandler接口,实现该接口的对象一般会封装代理模式中的目标对象,同时实现其中的invoke方法。以下是实现该接口的代码:
//DynamicProxyInvocationHandler.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxyInvocationHandler implements InvocationHandler {
private Object realService = null;
public DynamicProxyInvocationHandler(Object service) {
this.realService = service;
}
public Object invoke(Object proxy, Method m, Object[] args){
Object result = null;
System.out.println("您正在申请服务" + m.getName());
try {
result = m.invoke(realService , args);
}catch(Exception ex) {
System.exit(1);
}
System.out.println("您申请的服务 " + m.getName() + " 已经完成 ");
return result;
}
}

接口中的invoke方法包含三个参数:Object、Method、Object[],同时包含一个Object类型的返回值。该方法的含义为:使用Object[]类型的参数列表args调用proxy对象的m方法,返回Object类型的对象。 在上面的实现中,在调用具体对象的方法前首先打印正在申请某个对象的某个方法,接着调用某个对象的某个方法,在调用具体对象的方法后打印申请的服务已经完成。这就是我们上面所说的为真实对象增加功能。下面是一段最后的测试代码:
//DynamicProxyTest.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxyTest {
public static void main(String args[]) {
Service realService = new Service();
ServiceIF proxy = (ServiceIF)Proxy.newProxyInstance(
realService.getClass().getClassLoader(),
realService.getClass().getInterfaces(),
new DynamicProxyInvocationHandler(realService));
proxy.doService();
}
}
在测试中首先创建一个真实的服务对象,即代理模式中的目标对象,然后使用Proxy类的newProxyInstance静态方法,创建一个具体的代理对象,由于代理对象和被代理对象具有相同的接口ServiceIF,因此我们在该代理对象被创建后downcast为ServiceIF接口,接着调用该代理对象的服务方法。下图是执行结果图:




有兴趣可以继续研究编译器的实现、字节码的细节、以及虚拟机的实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: