一、什么是动态代理,动态代理的动态是什么意思?
与动态相对的是静态,静态代理是在代码编译时生成的。动态代理的动态是指在程序运行期生成的代理对象。
二、动态代理的使用和实现底层原理
接口
public interface OutInfo {
void printInfo();
}
实现类
public class Person implements OutInfo {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public void printInfo() {
System.out.println(name + "..." + age);
}
}
动态代理类最终底层调用的方法实现InvocationHandler
public class personHandler implements InvocationHandler
{
private Object obj;
public personHandler (Object obj) {
this.obj = obj;
}
/**
* proxy:代表动态代理对象
* method:代表正在执行的方法
* args:代表调用目标方法时传入的实参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.print("进入了代理\n");
Object result = method.invoke(obj, args);
System.out.print("时间为:" + new Date() + "\n\n");
return result;
}
}
生成动态代理类
public class DynamicProxy {
public static void main(String[] args) {
Person person = new Person("张三", 23);
OutInfo outInfoProxy = (OutInfo ) Proxy
.newProxyInstance(person.getClass().getClassLoader(), person .getClass().getInterfaces(), invocationHandler);
}
outInfoProxy.printInfo();
}
Proxy.newProxyInstance()方法产生了最终的代理对象 P r o x y , Proxy, Proxy,Proxy字节码反编译后的文件如下:
选取了比较重要的代码:
public final class $Proxy extends Proxy implements OutInfo {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy(InvocationHandler var1) throws {
super(var1);
}
public final void printInfo() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
}
所以最后代理对象$Proxy调用OutInfo 接口的printInfo()方法最后是调用了
super.h.invoke(this, m3, (Object[])null);
这个h就是
Proxy.newProxyInstance(person.getClass().getClassLoader(), person .getClass().getInterfaces(), invocationHandler);
传入的invocationHandler,看到最后就是调用到了invocationHandler的invoke。
invoke(this, m3, (Object[])null)
invoke(Object proxy, Method method, Object[] args)
三、jdk动态的特点
选取了比较重要的代码:
public final class $Proxy extends Proxy implements OutInfo {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy(InvocationHandler var1) throws {
super(var1);
}
public final void printInfo() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
}
还是最终生成的动态代理类
$Proxy extends Proxy implements OutInfo
继承了Proxy 类,实现了OutInfo接口,所以java中不能多重继承,当动态代理类实现了jdk中的Proxy.class类的时候,就只能通过实现目标接口的方式来实现拓展。
所以jdk的代理一定是基于接口实现