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接口,接着调用该代理对象的服务方法。下图是执行结果图:
有兴趣可以继续研究编译器的实现、字节码的细节、以及虚拟机的实现。
[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接口,接着调用该代理对象的服务方法。下图是执行结果图:
有兴趣可以继续研究编译器的实现、字节码的细节、以及虚拟机的实现。
相关文章推荐
- JDK动态代理源码分析之二
- jdk动态代理模式的原理解析
- Java JDK 动态代理(AOP)使用及实现原理分析
- 细说JDK动态代理的实现原理
- 深入探索spring技术内幕(六): JDK动态代理和cglib生成代理
- 学习JDK与CGLib两种动态代理机制
- jdk 动态代理
- java动态代理(JDK和cglib)
- JDK动态代理实现原理
- JDK动态代理
- 代理设计模式(普通静态代理、JDK动态代理、cglib动态代理)
- (转)java动态代理(JDK和cglib)
- 设计模式之JDK动态代理
- java动态代理(JDK和cglib)
- jdk动态代理(转载)
- JDK动态代理用法
- 对SpringAop的思考之基于jdk的动态代理
- java动态代理(JDK和cglib)
- JDK的动态代理机制