代理模式:给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。代理模式是一种结构型设计模式。
- 动态代理与静态代理一样
- 动态代理的代理类是动态生成的,不是我们直接写好的!
- 这里我们聊基于接口的JDK动态代理
在这里我么聊两个点
InvocationHandler 接口
每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法,点进去我们也可以发现只有一个方法:
其中的参数:
proxy: 指代我们所代理的那个真实对象
method: 指代的是我们所要调用真实对象的某个方法的Method对象
args: 指代的是调用真实对象某个方法时接受的参数
Proxy 类
Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,下面是我们常用的一个方法:
其中的参数:
loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
案例
先来一个接口里面有个卖房子的抽象方法:
package proxy;
public interface Rent {
public void getHouse();
}
再来个房东实现这个方法:
package proxy;
public class Host implements Rent {
@Override
public void getHouse() {
System.out.println("房东要卖房子房子");
}
}
这个时候假如有人要买房子房东亲自出马的话就是这样实现:
package proxy;
public class Client {
public static void main(String[] args) {
Host host = new Host();
host.getHouse();
}
}
结果也很明显:
主动出马直接把房子给卖了,但是我们有代理之后就变的有点不一样了,我们可以这样想。
房东要卖房子,但是不想自己出马去找买房子这个人,于是房东把房子交给了中间商代理他卖这个房子。
下面是实现的代码:
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 动态代理
//这个类用来自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
// //被代理的真实角色 (把房子交出来给中介)
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成得到代理类 (中间商)
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理本质,就是使用反射机制实现!
System.out.println("中间商为你找到了买房子的人");
//具体代理的事情在这里做
Object result = method.invoke(target, args);
return result;
}
}
下面是一个Client要买房子:
于是乎他来找中间商(new ProxyInvocationHandler()),这个里面的一个参数就是Proxy吧,再上一个代码中我们已经写好逻辑并且吧房子交给中间商,但是卖房子的时候要来画押吧,所有真实角色(房东)也要当场 于是有了(new Host()),最后完成交易。
package proxy;
public class Client {
public static void main(String[] args) {
//真实角色
Host housts = new Host();
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(housts);
Rent proxy = (Rent) pih.getProxy();
proxy.getHouse();
}
}
核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!