jdk动态代理实现原理(一)

2014-11-24 09:19:36 · 作者: · 浏览: 3
MoreeVan写在前面:
大神和diao炸天的亲请绕道..
关于代理模式的概念这里省去,大家可以放鸟尽情搜..
关于为什么叫动态代理,个人理解是代理的类是在运行时动态生成的,大家也可以参考网上的理解..
文笔很差,所以文字较少,都在代码和注释中..
=======一点不华丽的分割线-------------------------
开门见山,lets go..
java中可以通过jdk提供的 Proxy.newProxyInstance静态方法来创建动态代理对象,下面先来看看这个方法的实现
[java]
public static Object newProxyInstance(ClassLoader loader, Class< >[] interfaces, InvocationHandler h)
throws IllegalArgumentException {
//InvocationHandler不能为空,因为对代理对象的所有方法调用实际上都会委托到InvocationHandler的invoke方法,
//这个我们后面通过查看产生的代理类的源代码便会一目了然
if (h == null) {
throw new NullPointerException();
}
//这个是核心的地方,通过提供的ClassLoader和interface列表来产生代理类,具体的实现可以参考getProxyClass这个方法的实现,
//真正的工作是由sun.misc.ProxyGenerator这个类来完成的,可以google查看具体的逻辑.在我们的程序中通过设置
//System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true")可以查看产生的类文件
Class cl = getProxyClass(loader, interfaces);
//因为代理类继承了Proxy类.而Proxy中定义了构造函数protected Proxy(InvocationHandler h),所以可以反射得到Constructer实例
//创建代理对象
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());
}
}
下面通过个例子来说明下:
先来定义一个接口,jdk的动态代理基于接口来创建代理类,不能基于类的原因是java不支持多重继承,而代理类都会继承Proxy类(个人理解).
[java]
/**
* Subject
*
* @author Kevin Fan
* @since 2013-9-13 下午2:43:33
*/
public interface Subject {
void pub(String key, String content);
String sub(String key);
}
再来一个具体的实现,在代理模式中可以叫它的实例可以叫target,这个是真正执行操作的对象
[java]
/**
* SimpleSubject
*
* @author Kevin Fan
* @since 2013-9-13 下午2:45:03
*/
public class SimpleSubject implements Subject {
private Map msg = new ConcurrentHashMap();
public void pub(String key, String content) {
System.out.println("pub msg: key is " + key + ", content is " + content);
msg.put(key, content);
}
public String sub(String key) {
if (msg.containsKey(key)) {
String ret = msg.get(key);
System.out.println("sub msg: key is " + key + ", result is " + ret);
return ret;
}
return null;
}
}
好,接下来我们来写个动态代理工厂,根据 不同的target来创建动态代理对象
[java]
/**
* SubjectProxyFactory
*
* @author Kevin Fan
* @since 2013-9-13 下午2:47:24
*/
public class SubjectProxyFactory {
//TODO: cache
public static Subject getSubject(final Subject realSubject) {
return (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), new Class[] { Subject.class },
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("\naction before method inv