Java设计模式-代理模式之动态代理(附源代码分析)
Posted yutingliuyl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java设计模式-代理模式之动态代理(附源代码分析)相关的知识,希望对你有一定的参考价值。
Java设计模式-代理模式之动态代理(附源代码分析)
动态代理概念及类图
上篇中的静态代理是在编译的时候就确定了代理类详细类型。假设有多个类须要代理。那么就得创建多个。
另一点,假设Subject中新增了一个方法,那么相应的实现接口的类中也要相应的实现这些方法。
动态代理实现过程
一个详细的样例
package ProxyMode;
/*
* 抽象接口。相应类图中的Subject
*
*/
public interface Subject {
public void SujectShow();
}
package ProxyMode; public class RealSubject implements Subject{ @Override public void SujectShow() { // TODO Auto-generated method stub System.out.println("杀人是我指使的,我是幕后黑手!
By---"+getClass()); } }
package ProxyMode;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyHandler implements InvocationHandler {
private Object proxied;
public ProxyHandler( Object proxied )
{
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("准备工作之前:");
//转调详细目标对象的方法
Object object= method.invoke( proxied, args);
System.out.println("工作已经做完了!");
return object;
}
}
package ProxyMode;
import java.lang.reflect.Proxy;
public class DynamicProxy {
public static void main( String args[] )
{
RealSubject real = new RealSubject();
Subject proxySubject = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[]{Subject.class},
new ProxyHandler(real));
proxySubject.SujectShow();;
}
}
測试结果
准备工作之前: 杀人是我指使的,我是幕后黑手!
By---class ProxyMode.RealSubject 工作已经做完了!
Proxy和InvocationHandler重要部分源代码分析
java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
清单 1. Proxy 的静态方法
// 方法 1: 该方法用于获取指定代理对象所关联的调用处理器,比方上面代码中的ProxyHandler
static InvocationHandler getInvocationHandler(Object proxy)
// 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
static Class getProxyClass(ClassLoader loader, Class[] interfaces)
// 方法 3:该方法用于推断指定类对象是否是一个动态代理类
static boolean isProxyClass(Class cl)
// 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
static Object newProxyInstance(ClassLoader loader, Class[] interfaces,
InvocationHandler h)
public static Object newProxyInstance(ClassLoader loader, Class<?
>[] interfaces, InvocationHandler h) throws IllegalArgumentException { // 检查 h 不为 空,否则抛异常 if (h == null) { throw new NullPointerException(); } // 获得与制定类装载器和一组接口相关的代理类类型对象 Class cl = getProxyClass(loader, interfaces); // 通过反射获取构造函数对象并生成代理类实例 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()); } }
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
这个步骤通过一个循环来完毕,检查通过后将会得到一个包括全部接口名称的字符串数组,记为 String[] interfaceNames
for (int i = 0; i < interfaces.length; i++) { // 验证类载入程 序 解 析 该接口到同一类对象的名称。
String interfaceName = interfaces[i].getName(); Class<?> interfaceClass = null; try { interfaceClass = Class.forName(interfaceName, false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != interfaces[i]) { throw new IllegalArgumentException( interfaces[i] + " is not visible from class loader"); } // 验证类对象真正代表一个接口 if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } //验证这个接口是不是反复的 if (interfaceSet.contains(interfaceClass)) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } interfaceSet.add(interfaceClass); //interfaceset是一个hashset集合 interfaceNames[i] = interfaceName; }
缓存表是一个 HashMap 实例,正常情况下它将存放键值对(接口名字列表。动态生成的代理类的类对象引用)。当代理类正在被创建时它会暂时保存(接口名字列表,pendingGenerationMarker)。标记 pendingGenerationMarke 的作用是通知兴许的同类请求(接口数组同样且组内接口排列顺序也同样)代理类正在被创建。请保持等待直至创建完毕。
synchronized (cache) {
do {
// 以接口名字列表作为关键字获得相应 cache 值
Object value = cache.get(key);
if (value instanceof Reference) {
proxyClass = (Class) ((Reference) value).get();
}
if (proxyClass != null) {
// 假设已经创建,直接返回,这里很重要。假设已经创建过代理类,那么不再创建
return proxyClass;
} else if (value == pendingGenerationMarker) {
// 代理类正在被创建,保持等待
try {
cache.wait();
} catch (InterruptedException e) {
}
// 等待被唤醒,继续循环并通过二次检查以确保创建完毕,否则又一次等待
continue;
} else {
// 标记代理类正在被创建
cache.put(key, pendingGenerationMarker);
// break 跳出循环已进入创建过程
break;
} while (true);
}
首先是确定代理类所在的包,其原则如前所述。假设都为 public 接口,则包名为空字符串表示顶层包。假设全部非 public 接口都在同一个包。则包名与这些接口的包名相同;假设有多个非 public 接口且不同包,则抛异常终止代理类的生成。
确定了包后。就開始生成代理类的类名,相同如前所述按格式“$ProxyN”生成。
// 动态地生成代 理类的字节码数组
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces);
try {
// 动态地定义新生成的代理类
proxyClass = defineClass0(loader, proxyName, proxyClassFile, 0,
proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
// 把生成的代理类的类对象记录进 proxyClasses 表
proxyClasses.put(proxyClass, null);
synchronized (cache) {
if (proxyClass != null) {
cache.put(key, new WeakReference<Class<?>>(proxyClass));
} else {
cache.remove(key);
}
cache.notifyAll();
}
java.lang.reflect.InvocationHandler:这是调用处理器接口,它自己定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对托付类的代理訪问。
// 该方法负责集中处理动态代理类上的所 有方法调用。
//第一个參数既是代理类实例, //第二个參数是被调用的方法对象 // 第三个方法是调用參数。调用处理器依据这三个參数进行预处理或分派到托付类实例上发射运行 Object invoke(Object proxy, Method method, Object[] args)
//这种方法是 Proxy源代码中的
protected Proxy(InvocationHandler h) {
this.h = h;
}
来看NewProxyInstance方法生成的$Proxy0代理类的源代码
public final class $Proxy0 extends Proxy implements Subject {
private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals",
new Class[] { Class.forName("java.lang.Object") });
m0 = Class.forName("java.lang.Object").getMethod("hashCode",
new Class[0]);
m3 = Class.forName("***.RealSubject").getMethod("request",
new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString",
new Class[0]);
} catch (NoSuchMethodException nosuchmethodexception) {
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
} catch (ClassNotFoundException classnotfoundexception) {
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
} //static
public $Proxy0(InvocationHandler invocationhandler) {
super(invocationhandler);
}
@Override
public final boolean equals(Object obj) {
try {
return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public final int hashCode() {
try {
return ((Integer) super.h.invoke(this, m0, null)).intValue();
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final void SubjectShow() {
try {
super.h.invoke(this, m3, null); //就是这个地方 调用h.invoke()
return;
} catch (Error e) {
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
@Override
public final String toString() {
try {
return (String) super.h.invoke(this, m2, null);
} catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
以上是关于Java设计模式-代理模式之动态代理(附源代码分析)的主要内容,如果未能解决你的问题,请参考以下文章