代理模式是一种设计模式
静态代理
- 抽象角色:接口或者抽象类
- 真实角色:委托类,被代理的角色
- 代理角色:代理类,代理真实角色
- 客户:客户类,访问代理对象
- 优点:真实角色只需要关注核心的业务逻辑;扩展性强,可以在不改变原有代码的基础上扩展新的功能
- 缺点:每代理一个真实角色,就需要产生一个代理角色,代码量会大大增加
动态代理
顾名思义,就是动态产生的代理,不是我们写死的
- 基于接口:JDK动态代理
- 基于类:cglib
难点:
如何根据加载到内存中的委托类,动态创建一个被代理类;
如何让代理类动态地调用委托类中的方法
怎么实现动态代理?
先写个接口:租房
public interface Rent {//租房接口
public void rent();
}
然后是委托类:房东
public class Landlord implements Rent {
@Override
public void rent() {
System.out.println("我要把房子租出去");
}
}
然后是动态代理类
通过newProxyInstance()
创建一个代理类对象
要传3个参数:对象的类加载器、对象实现的接口(代理类通过这个知道委托类实现了哪些接口)、InvocationHandler(proxy代理实例的调用处理程序实现的一个接口)
public class DynamicProxy {
//调用此方法返回代理类的对象,解决难点一
public static Object getProxyInstance(Object obj){//这个obj是委托类对象
MyInvocationHandler handler = new MyInvocationHandler();
handler.setObj(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
}
}
而这个InvocationHandler需要创建一个类实现这个接口
通过invoke()
让代理类动态地调用委托类中的同名的方法
也要传3个参数:代理类返回的对象、代理类对象调用的方法、调用的方法的参数
class MyInvocationHandler implements InvocationHandler {
private Object obj;//根据委托类对象类型进行赋值
public void setObj(Object obj) {//实例化
this.obj = obj;
}
//通过代理类对象调用某方法时,就会自动调用invoke方法
//将委托类要执行的方法声明在invoke方法中
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
return method.invoke(obj, objects);//委托类执行的方法的返回值就作为本类中invoke方法的返回值
}
}
然后测试一下
public static void main(String[] args) {
Landlord landlord = new Landlord();
//agent:代理类的对象也实现Rent接口
Rent agent = (Rent) DynamicProxy.getProxyInstance(landlord);
agent.rent();
}