动态代理
1.什么是代理(中介)
目标对象/被代理对象 ------ 房主:真正的租房的方法
代理对象 ------- 黑中介:有租房子的方法(调用房主的租房的方法)
执行代理对象方法的对象 ---- 租房的人
流程:我们要租房----->中介(租房的方法)------>房主(租房的方法)
抽象:调用对象----->代理对象------>目标对象
2.静态代理
静态代理图解:
图中的代理对象是自己编写一个类,去调用目标对象的方法,这就是静态代理。
3.动态代理
java.lang.reflect.Proxy
动态代理:不用手动编写一个代理对象,不需要编写与目标对象相同的方法,这个过程,在运行时的内存中动态生成代理对象。------字节码对象级别的代理对象
注意:JDK的Proxy方式实现的动态代理 目标对象必须有接口 没有接口不能实现jdk版动态代理
为什么要实现接口?
代理对象和目标对象的方法肯定要一样,代理对象调用目标对象同名的方法结果可能是不一样的。代理对象是在目标对象方法基础上做操作。换言之目标对象有的方法,代理对象也要有。
举例:房东卖房子->中介(中介调用房东卖房子的方法)->其实中介也有一个卖房方法,但是中介可以在卖房前后搞一些外快。
动态代理的API:
在jdk的API中存在一个Proxy中存在一个生成动态代理的的方法newProxyInstance
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
代码演示:
public class ProxyTest {
public static void main(String[] args) {
//动态创建代理对象,返回代理对象。
//为什么可以TargerInterfacee接口接收?
//代理对象和目标对象实现了同一接口,返回的又是代理对象,当然可以用TargerInterfacee接口接收。
//Target.class.getClassLoader():代理对象需要和目标对象相同的类加载器。
//Target.class.getInterfaces():获取目标对象接口,就相当于代理对象实现了目标对象接口(底层会操作)。
//InvocationHandler:处理器中的invoke方法就是代理对象,每次调用都是执行的方法。
TargerInterface ti = (TargerInterface) Proxy.newProxyInstance(Target.class.getClassLoader(),
Target.class.getInterfaces(), new InvocationHandler() {
@Override
//被执行几次?------- 看代理对象调用方法几次
//代理对象调用接口相应方法 都是调用invoke
/*
* proxy:是代理对象(大部分不用上,如果直接打印就是死循环)
* method:代表的是目标方法的字节码对象
* args:代表是调用目标方法时参数(注意args:是从代理对象调用方法时传入的参数,然后再传给目标方法。)
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用目标方法前执行操作");
//使用反射执行方法
Object invoke = method.invoke(new Target(),args);
System.out.println("调用目标方法后执行操作");
//目标方法返回值,返给给代理对象
return invoke;
}
});
//目标对象方法无返回值,代理也就没有。
ti.method();
System.out.println("-------------------");
//代理对象的返回值,就是invoke方法的返回值。
String method2 = ti.method2();
System.out.println("method2:"+method2);
System.out.println("-------------------");
//代理对象调用方法,传入参数会传给invoke方法中的args参数,通过args参数可以传给目标方法的参数。
int method3 = ti.method3(100);
System.out.println("method3:"+method3);
}
}
目标类
public class Target implements TargerInterface {
@Override
public void method() {
System.out.println("method");
}
@Override
public String method2() {
System.out.println("method2");
return "且随疾风前行身后亦需留心";
}
@Override
public int method3(int i) {
System.out.println("method3");
return i;
}
}
代理和目标都要实现的接口
public interface TargerInterface {
public abstract void method();
public abstract String method2();
public abstract int method3(int i);
}
结果:
调用目标方法前执行操作
method
调用目标方法后执行操作
-------------------
调用目标方法前执行操作
method2
调用目标方法后执行操作
method2:且随疾风前行身后亦需留心
-------------------
调用目标方法前执行操作
method3
调用目标方法后执行操作
method3:100