代理模式
代理模式就是在不修改原有代码的情况下,通过代理对象完成一些新增功能(开闭原则)
也就是横切业务,面向切面编程
代理模式分类:
- 静态代理
- 动态代理
使用场景:
- SpringAOP底层
1. 静态代理
角色分析:
- 抽象角色:一般使用接口或者抽象类来解决
- 真实角色:被代理角色
- 代理角色:代理真实角色,一般做一些附属操作(切入功能)
// 接口
public interface Rent{
void rent();
}
// 真实对象
public class Landlord implements Rent{
public void rent(){
System.out.println("出租房子");
}
}
// 代理对象
public class Proxy implements Rent{
private Landlord landlord;
public Proxy(Landlord landlord){
this.landlord = landlord;
}
// 中介租房,加了附属操作
public void rent(){
// 前置通知
lookHouse();
landlord.rent();
// 后置通知
contract();
fees();
}
// 代理对象扩展方法,看房子
public void lookHouse(){
System.out.println("看房子");
}
// 签合同
public void contract(){
System.out.println("签合同");
}
// 中介费
public void fees(){
System.out.println("签合同");
}
}
静态代理的缺点就是一个真实角色会产生一个代理角色,所以需要动态代理
2. 动态代理
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是直接写好的
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口:JDK动态代理
- 基于类:cglib
- java字节码:JAVAssist
相关类:Proxy、 InvocationHandler
public class ProxyTest implements InvocationHandler{
// 代理对象
private Object target;
public setTarget(Object target){
this.target = target;
}
//生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(), this)
}
// 处理代理对象实例方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
// 切入
log(method.getName());
// 调用真实对象方法, 动态代理的本质是反射(invoke就是反射中的方法调用)
Object result = method.invoke(target, args);
return result;
}
// 当需要添加功能时只需要横切
public void log(String name){
System.out.println("执行了"+name+"方法");
}
}
调试
public class Client{
public static viod main(String[] args){
// 真是对象
Rent rent = new Rent();
// 代理对象生成类
ProxyTest proxy = new ProxyTest();
// 设置代理的真实对象
proxy.setTarget(rent);
// 获取代理对象
Object obj = proxy.getProxy();
// 调用出租方法
obj.rent();
}
}
动态代理类代理的是一个接口,一类业务
代理模式的好处:
- 可以使真实角色的操作更纯粹
- 公共业务交给代理实现业务分工
- 公共业务发生扩展方便管理