为其他对象提供一种代理,以控制对这个对象的访问,在访问对象和目标对象之间起到中介作用
代理模式分三种角色
抽象角色:定义角色的业务方法,供真实角色和代理角色实现
真实角色:实现抽象角色
代理角色: 实现抽象角色,内部包含对真实角色的调用,可以访问、控制或扩展真实角色功能
代理分为静态代理和动态代理
动态代理有两种
JDK和CGLIB
JDK: 基于反射机制实现,要求目标类必须实现一个或多个接口,代理对象在运行时动态创建,通过实现接口的方式来代理目标类;因为需要实现目标接口,性能相对较低,但应用较广泛,使用大多数代理场景的需求,常见Spring中事务处理、日志记录等;
CGLIB:是基于ASM字节码框架实现,可以代理没有实现接口的类,通过动态生成目标类的子类来实现代理,因为不需要实现目标类接口,性能相对较高,但不能代理final类和final方法,以及一些无法生成子类的类,常见与Spring中AOP切面。
应用场景:包含目标对象、增强目标对象
主要优点:实现访问对象和目标对象的分离,降低了系统的耦合程度,易于扩展,并对目标对象起到保护作用;
缺点:增加类的数目,增加代理对象,请求处理速度变慢,增加了系统的复杂性
示例
静态代理
// 火车站接口,有卖票功能
public interface TrainStation {
void sellTickets();
}
// 广州火车站卖票
public class GuangzhouTrainStation implements TrainStation {
@Override
public void sellTickets() {
System.out.println("广州火车站卖票啦");
}
}
// 代售点卖票(代理类)
public class ProxyPoint implements TrainStation {
// 目标对象(代理火车站售票)
private TrainStation station = new GuangzhouTrainStation();
@Override
public void sellTickets() {
System.out.println("代售加收5%手续费");
station.sellTickets();
}
public static void main(String[] args) {
ProxyPoint proxyPoint = new ProxyPoint();
// 代售加收5%手续费
// 广州火车站卖票啦
proxyPoint.sellTickets();
}
}
jdk动态代理
// 火车站接口,有卖票功能
public interface TrainStation {
void sellTickets();
}
// 广州火车站卖票
public class GuangzhouTrainStation implements TrainStation {
@Override
public void sellTickets() {
System.out.println("广州火车站卖票啦");
}
}
// 深圳火车站卖票
public class ShenzhenTrainStation implements TrainStation {
@Override
public void sellTickets() {
System.out.println("深圳火车站卖票啦");
}
}
// 代售点卖票(代理类)
public class ProxyPoint implements InvocationHandler {
private TrainStation trainStation;
public TrainStation getProxyObject(TrainStation trainStation) {
this.trainStation = trainStation;
Class<? extends TrainStation> clazz = trainStation.getClass();
return (TrainStation) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代售火车票收取5%手续费");
return method.invoke(this.trainStation, args);
}
}
// 测试
public static void main(String[] args) {
ProxyPoint proxy = new ProxyPoint();
TrainStation guangzhouTrainStation = proxy.getProxyObject(new GuangzhouTrainStation());
// 代售火车票收取5%手续费
// 广州火车站卖票啦
guangzhouTrainStation.sellTickets();
TrainStation shenzhenTrainStation = proxy.getProxyObject(new ShenzhenTrainStation());
// 代售火车票收取5%手续费
// 深圳火车站卖票啦
shenzhenTrainStation.sellTickets();
}
cglib动态代理
// 代售点卖票(代理类)
public class ProxyPoint implements MethodInterceptor {
public TrainStation getProxyObject(Class<? extends TrainStation> trainStation) {
//创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数
Enhancer enhancer =new Enhancer();
//设置父类的字节码对象
enhancer.setSuperclass(trainStation);
//设置回调函数
enhancer.setCallback(this);
//创建代理对象并返回
return (TrainStation) enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代售火车票收取5%手续费");
return methodProxy.invokeSuper(o, objects);
}
}
// 测试
public static void main(String[] args) {
ProxyPoint proxy = new ProxyPoint();
TrainStation guangzhouTrainStation = proxy.getProxyObject(GuangzhouTrainStation.class);
// 代售火车票收取5%手续费
// 广州火车站卖票啦
guangzhouTrainStation.sellTickets();
TrainStation shenzhenTrainStation = proxy.getProxyObject(ShenzhenTrainStation.class);
// 代售火车票收取5%手续费
// 深圳火车站卖票啦
shenzhenTrainStation.sellTickets();
}