注:最近学习hessian远程调用,看到hessian服务端最后利用动态代理来调用服务,就学习了下动态代理。动态代理的文章有很多很详细的介绍,本篇是本人学习的一个记录,内容较简单。
1.动态代理定义
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
代理模式UML图:
2.获取动态代理过程:
//具体执行服务的接口
Say animal = new Dog();
//被代理interface
Class[] Interfaces = new Class[]{Say.class};
//Invocationhandler 分发接口
InvocationHandler handler = new AnimalProxy(animal);
//proxy classloader 分发接口的classloader
ClassLoader loader = handler.getClass().getClassLoader();
//生成proxy
Say dog = (Say) Proxy.newProxyInstance(loader, Interfaces, handler);
dog.say();
其中:
loader:proxy的classloader
interfaces:被代理的接口
InvocationHandler:分发的接口,具体是实现InvocationHandler的类,其中method.invoke(animal, args)调起具体接口的方法。
newProxyInstance的过程分析:
1.利用Class cl = getProxyClass0(loader, interfaces)
根据loader,interfaces在内存中生成lesson1_1.Proxy.Say.class的类
//设置saveGeneratedFiles可以输出class文件到本地
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true")
2.利用Class.forName装载JVM后
3.利用final Constructor cons = cl.getConstructor(new Class[]{ InvocationHandler.class })得到构造函数
4.利用newInstance(cons, handler)生成Proxy
代码:
/**
*接口定义
*/
public interface Say {
void say();
}
/**
* 接口具体实现类
*/
public class Cat implements Say {
@Override
public void say() {
System.out.println("miaomiao");
}
}
/**
* 接口具体实现类
*/
public class Dog implements Say {
@Override
public void say() {
System.out.println("wangwang");
}
}
/**
* 分发类,即proxy
*/
public class AnimalProxy implements InvocationHandler {
public Say animal;
public AnimalProxy(){}
public AnimalProxy(Say animal) {
this.animal = animal;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before proxy animal say:");
Object object = method.invoke(animal, args);
System.out.println("and is over");
return object;
}
}
public static void main(String[] args) throws IOException {
Say animal = new Dog();
//被代理interface
Class[] Interfaces = new Class[]{Say.class};
//Invocationhandler
InvocationHandler handler = new AnimalProxy(animal);
//proxy classloader
ClassLoader loader = handler.getClass().getClassLoader();
//生成proxy
Say dog = (Say) Proxy.newProxyInstance(loader, Interfaces, handler);
System.out.println("proxy:"+dog.getClass());
System.out.println("dir:"+System.getProperty("user.dir")+ File.separator);
dog.say();
}
结果:
proxy:class sun.proxy.$Proxy0
dir:E:\work\study\
before proxy anima say:
wangwang
and is over