(1)动态代理首先提供一个调度处理器接口(Invocationhandler),该接口实例封装了我们要代理的对象实例的数据。
public class TranceHander implements InvocationHandler{
private Object tObject;
public TranceHander(Object t){
tObject=t;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("被代理对象:"+tObject);
System.out.println("方法:"+method.getName());
return method.invoke(tObject,args);//方法反射
}
}
(2)使用Proxy类的newProxyInstance方法创建代理对象或getProxyClass方法获得代理类Class。
测试mian方法中,写了一个代理类,从1-1000的整数数组中使用二分查找随机查找一个整数,实现对象比较和toString接口代理
public class ProxyTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Object[] elements=new Object[1000];
for(int i=0;i1;//被代理对象
InvocationHandler handler=new TranceHander(value);//构建调度处理器
Object proxy=Proxy.newProxyInstance(null, new Class[]{Comparable.class}, handler);
elements[i]=proxy;
}
Integer key=new Random().nextInt(1000)+1;
int res=Arrays.binarySearch(elements, key);
if(res>=0){
System.out.println(elements[res].toString());
}
System.out.println("查找Key:"+key);
}
}
(1)代理对象生成:
Object proxy=Proxy.newProxyInstance(null, new Class[]{Comparable.class}, handler);
(2)查看Proxy类的newProxyInstance方法
从生成对象方法中,我们看到三个关键的地方:
Class> cl = getProxyClass0(loader, interfaces);//得到代理类
final Constructor> cons = cl.getConstructor(constructorParams);
newInstance(cons, ih);//将InvocationHandler h传入代理对象中
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, interfaces);
}
/*
* Look up or generate the designated proxy class.
*/
Class> cl = getProxyClass0(loader, interfaces);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
final Constructor> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
// create proxy instance with doPrivilege as the proxy class may
// implement non-public interfaces that requires a special permission
return AccessController.doPrivileged(new PrivilegedAction
(3)生成Proxy类,查看getProxyClass0方法,
这个方法有点长,抽取关键的地方:
1.先抽取被代理类实现的接口Interface,检测是否符合要求
/* collect interface names to use as key for proxy class cache */
String[] interfaceNames = new String[interfaces.length];
// for detecting duplicates
Set> interfaceSet = new HashSet<>();
for (int i = 0; i < interfaces.length; i++) {
/*
* Verify that the class loader resolves the name of this
* interface to the same Class object.
*/
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");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.contains(interfaceClass)) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
interfaceSet.add(interfaceClass);
interfaceNames[i] = interfaceName;
}
查看代理对象缓存中是否有我们要创建的代理类,如果有,直接获取;没有则创建
如果有则: return proxyClassCache.get(loader, interfaces);
没有则创建,先定义代理类的包名,如果所有的接口都是公共的,则默认将创建的类放在String PROXY_PACKAGE = “com.sun.proxy”;中,若果存在
非public接口则所有的非public接口必须在同一包下,代理类也放在此包下,否则系统抛异常。
"white-space:pre"> for (int i = 0; i < interfaces.length; i++) {
int flags = interfaces[i].getModifiers();
if (!Modifier.isPublic(flags)) {
String name = interfaces[i].getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
接下来创建类,和将字节码写入类文件中:
byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces);
proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
return proxyClass;
(4)创建代理实例,将
newInstance(cons, ih);//将InvocationHandler h传入代理对象中
看完源码,我还是有点困惑,直到我看到生成的代理类文件源码后,豁然开朗。其实主要一步就在于生成类
的过程,类文件中建立被代理对象接口的invoke调用,话不多说看源码(我直接在测试用例调用的ProxyGenerator.generateProxyClass( proxyName, interfaces)接口生成的)
public static void main(String[] args) {
// TODO Auto-generated method stub
Integer value=1;
InvocationHandler handler=new TranceHander(value);//构建调度处理器
Object proxy=Proxy.newProxyInstance(null, Integer.class.getInterfaces(), handler);
String path = "D://aaa.class";
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0",Integer.class.getInterfaces());
FileOutputStream out = null;
try {
out = new FileOutputStream(path);
out.write(classFile);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
接着看class文件的反编译源码吧,直接用的Method的反射机制实现的代理,equal、hascode、toString方法是所有类都有的,compareTo则是被代理对象的实现接口:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy
implements Comparable
{
private static Method m3;
private static Method m1;
private static Method m0;
private static Method m2;
public $Proxy0(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final int compareTo(Object paramObject)
throws
{
try
{
return ((Integer)this.h.invoke(this, m3, new Object[] { paramObject })).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final boolean equals(Object paramObject)
throws
{
try
{
return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
throws
{
try
{
return ((Integer)this.h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
throws
{
try
{
return (String)this.h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m3 = Class.forName("java.lang.Comparable").getMethod("compareTo", new Class[] { Class.forName("java.lang.Object") });
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]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}