代理模式(Proxy Pattern)为其他对象(类)提供一种代理,以控制对这个对象(类)的访问。代理对象在客户端和目标对象之间起到中介的作用。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
当直接访问对象会遇到一些问题时,例如:有些对象由于一些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),这时直接访问就不是一种好的选择。
代理的思想在实际中也有很多的运用,例如:Windows快捷方式,Spring AOP的实现。
代理模式的应用场景:保护目标对象(控制对目标对象的访问)、增强目标对象
代理模式的优点:
- 代理模式能将代理对象与真实被调用的目标对象分离
- 一定程度上降低了系统的耦合度,扩展性好
- 保护目标对象
- 增强目标对象
代理模式的缺点:
- 代理模式会造成系统设计中类的数目增加
- 在客户端和目标对象间增加一个代理对象,会造成请求处理速度变慢
- 增加系统的复杂度
相关设计模式:装饰者模式、适配器模式
注意:
- 适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口
- 装饰器模式为了增强功能,而代理模式是为了加以控制
代理分为静态代理和动态代理,而动态代理又有两种实现方式:
- JDK动态代理(无法代理类,只能代理接口)
- CGLib代理(通过继承,使用时要注意final修饰符)
接下来,我用一个简易下单的方式对代理模式进行实现
- 静态代理
步骤一:创建一个实体对象
public class Order {
private Object orderInfo;
private Integer userId;
public Object getOrderInfo() {
return orderInfo;
}
public void setOrderInfo(Object orderInfo) {
this.orderInfo = orderInfo;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
}
步骤二:创建一个接口
public interface IOrderService {
int saveOrder(Order order);
}
步骤三:创建接口的实现类
public class OrderServiceImpl implements IOrderService {
private IOrderDao orderDao;
@Override
public int saveOrder(Order order) {
orderDao = new OrderDaoImpl();
System.out.println("service层调用dao层方法添加订单");
return orderDao.insert(order);
}
}
步骤四:创建dao层接口
public interface IOrderDao {
int insert(Order order);
}
步骤五:创建dao层接口的实现类
public class OrderDaoImpl implements IOrderDao {
@Override
public int insert(Order order) {
System.out.println("Dao层添加Order成功");
return 1;
}
}
JDK静态代理实现之创建静态代理类
- java.lang.reflect.Proxy:生成动态代理类和对象;
- java.lang.reflect.InvocationHandler(处理器接口):可以通过invoke方法实现
public class OrderServiceStaticProxy {
private IOrderService iOrderService;
// 对IOrderService接口中的方法进行增强
public int saveOrder(Order order) {
beforeMethod(order);
iOrderService = new OrderServiceImpl();
afterMethod();
int result = iOrderService.saveOrder(order);
return result;
}
private void beforeMethod(Order order) {
System.out.println("静态代理 before code");
}
private void afterMethod() {
System.out.println("静态代理 after code");
}
}
JDK动态代理实现之创建动态代理类
public class OrderServiceDynamicProxy implements InvocationHandler {
// 目标对象
private Object target;
public OrderServiceDynamicProxy(Object target) {
this.target = target;
}
public Object bind() {
Class<? extends Object> cls = target.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object argObject = args[0];
beforeMethod(argObject);
Object object = method.invoke(target, args);
afterMethod();
return object;
}
private void beforeMethod(Object obj) {
System.out.println("动态代理 before code");
}
private void afterMethod() {
System.out.println("动态代理 after code");
}
}
Cglib 动态代理
Cglib 动态代理是针对代理的类, 动态生成一个子类, 然后子类覆盖代理类中的方法, 如果是private或是final类修饰的方法,则不会被重写。
CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。两者没有什么本质的区别。