在java中有多种动态代理技术,比如JDK,CGLIB,Javassist,ASM,其中最常用是JDK动态代理和CGLIB。JDK动态代理是JDK自带的,是java.lang.reflect.*包提供的方式,它必须要借用接口才能产生代理对象。我们就深入解析源码了解它是如何生成代理对象,又如何代理逻辑的。
一.首页它要用到接口,先定义一个接口
public interface animal {
public void isAnimal();
}
二.实现类
public class dog implements animal{
public void isAnimal()
{
System.out.println("我是动物");
}
}
三.实现代理逻辑
//这个类是代理类的逻辑,因为在生成的代理类中会调用这个invoke。
public class handle implements InvocationHandler {
private dog d;
public handle(dog d) {
this.d = d;
}
//第一个参数是代理类,第2个是要执行的方法,第3个是参数
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.err.println("before");
// 执行某对象的方法,第一个参数是对象,第2个是参数,如果有返回值则返回,没有则null
Object object= method.invoke(d, args);
System.err.println("after");
return object;
}
}
在JDK动态代理中,要实现代理逻辑类必须去实现java.lang.reflect.InvocationHandler接口,它里面定义了一个invoke方法(为什么一定要实现这个接口呢,等一下会说到,因为生成的代理对象默认调用的是这个方法)
四.测试,生成代理对象
public class test {
public static void main(String arg[])
{ dog d=new dog();
//生成代理对象,参数分别是:被代理对象的类加载器,被代理对象的接口数组,代理逻辑。
//当然被代理对象的类加载器也可以这样得到d.getClass().getClassLoader()
animal a=(animal)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),d.getClass().getInterfaces(),new handle(d));
a.isAnimal(); //调用代理对象的isAnimal()方法
}
}
结果是:
before
我是动物
after
Process finished with exit code 0
其中对于第8行,a.isAnimal();调用代理对象的isAnimal()方法为什么会调用invok()方法呢,因为生成代理对象的isAnimal()方法调用this.invoke()。为了解释这个,我们来了解生成代理对象的过程
五.进入到Proxy类的newProxyInstance方法:
public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
/*
* Look up or generate the designated proxy class.
*/
Class cl = getProxyClass(loader, interfaces);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
Constructor cons = cl.getConstructor(constructorParams);
return 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());
}
}
关键是这2行:
// 创建代理类
Class cl = getProxyClass(loader, interfaces);
// 实例化代理对象
Constructor cons = cl.getConstructor(constructorParams);
返回的是代理类的实例化对象。接下来的调用就很清晰了。
那么,JDK动态代理最核心的关键就是这个方法:
Class cl = getProxyClass(loader, interfaces);
进入该方法,这个方法很长,前面很多都是铺垫,在方法的最后调用了一个方法:
//参数分别是:代理对象的类名,被代理对象接口集合
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
这个方法就是生成代理对象的2进制流,我们写入到文件中
public class test {
public static void main(String arg[])
{ dog d=new dog();
byte[] bs = ProxyGenerator.generateProxyClass("AudiImpl", d.getClass().getInterfaces());
try {
new FileOutputStream(new File("d:/AudiImpl.class")).write(bs);
}catch (Exception e)
{ } }}
并反编译成java文件如:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import me.wuwenbin.noteblogv4.jdktest.animal;
public final class AudiImpl
extends Proxy
implements animal
{
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public AudiImpl(InvocationHandler paramInvocationHandler)
{
super(paramInvocationHandler);
}
public final boolean equals(Object paramObject)
{
try
{
return ((Boolean)h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final String toString()
{
try
{
return (String)h.invoke(this, m2, null);
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final void isAnimal()
{
try
{
h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
public final int hashCode()
{
try
{
return ((Integer)h.invoke(this, m0, null)).intValue();
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("me.wuwenbin.noteblogv4.jdktest.animal").getMethod("isAnimal", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException localNoSuchMethodException)
{
throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
}
catch (ClassNotFoundException localClassNotFoundException)
{
throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
}
}
}
发现不止我们的接口的方法,还有默认的方法也被代理了,我们可以看到53行
public final void isAnimal()
{
try
{
h.invoke(this, m3, null);
return;
}
catch (Error|RuntimeException localError)
{
throw localError;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
调用了,调用了代理逻辑的invoke()方法,并把方法也传入进去了,利用了方法的反射,执行实现类的当前方法,当然在执行实现类前已经加入了其他执行过程输出。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.err.println("before");
// 执行某对象的方法,第一个参数是对象,第2个是参数,如果有返回值则返回,没有则null
Object object= method.invoke(d, args);
System.err.println("after");
return object;
}
原创来源:滴一盘技术