设计模式-代理模式
Posted 一菜一汤
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-代理模式相关的知识,希望对你有一定的参考价值。
代理模式
1.定义与类型
- 为其他对象提供一种代理,以控制这么对象的访问
- 代理对象在客户端和目标对象之间起中介作用
- 类型:增强型
2.适用场景
- 保护目标对象
- 增强目标对象
3.优点
- 代理模式能将代理对象与真实对象被调用的目标对象分离
- 一定程度上降低了代码的耦合度,扩展性好
- 保护目标对象
- 增强目标对象
4.缺点
- 代理模式会造成系统设计中类的数目增加
- 在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
- 增加系统的复杂度
5.扩展
- 静态代理
- 动态代理(Jdk中只有实现接口的类代理)
- CGlib代理
6.相关设计模式
- 代理模式和装饰者模式
- 代理模式和适配器模式
7. Coding
7.1 静态代理
-
创建common的dao service层,见代码
- 订单实体类Order
public class Order private String orderInfo ; private Integer userId; public String getOrderInfo() return orderInfo; public void setOrderInfo(String orderInfo) this.orderInfo = orderInfo; public Integer getUserId() return userId; public void setUserId(Integer userId) this.userId = userId; @Override public String toString() return "Order" + "orderInfo='" + orderInfo + '\\'' + ", userId=" + userId + '';
- servie层接口及实现类
public interface IOrderService int saveOrder(Order order); public class IOrderServiceImpl implements IOrderService private IOrderDao orderDao; @Override public int saveOrder(Order order) orderDao = new IOrderDaoImpl(); System.out.println("Service层调用Dao层添加Order"); return orderDao.insert(order);
- dao层接口及实现类
public interface IOrderDao int insert(Order order); public class IOrderDaoImpl implements IOrderDao @Override public int insert(Order order) System.out.println("Dao层添加订单成功!"); return 1;
-
创建代理类
public class OrderServiceStaticProxy
private IOrderService orderService;
public void saveOrder(Order order)
beforeProxy();
// 分库
orderService = new IOrderServiceImpl();
Integer userId = order.getUserId();
int dbNum = userId % 2;
System.out.println("静态代理分配到【db" + dbNum + "】处理数据");
// 设置分配的数据库
DataSourceContentHolder.setDBType("db" + dbNum);
afterProxy();
orderService.saveOrder(order);
public void beforeProxy()
System.out.println("前置代理类增强方法");
public void afterProxy()
System.out.println("后置代理类增强方法");
- 模拟Spring分库
public class DataSourceContentHolder
private static final ThreadLocal<String> CONTENT_HOLDER = new ThreadLocal<>();
public static void setDBType(String dbType)
CONTENT_HOLDER.set(dbType);
public static String getDBType()
return CONTENT_HOLDER.get();
public static void remove()
CONTENT_HOLDER.remove();
public class DynamicDaraSource extends AbstractRoutingDataSource
@Override
protected Object determineCurrentLookupKey()
return DataSourceContentHolder.getDBType();
- Test测试
public class Test
public static void main(String[] args)
Order order = new Order();
order.setUserId(1);
OrderServiceStaticProxy staticProxy = new OrderServiceStaticProxy();
staticProxy.saveOrder(order);
控制台输出:
- UML类图
现在可以看到,代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。
上面介绍的是静态代理的内容,为什么叫做静态呢?因为它的类型是事先预定好的。
代理的目的:增强/扩展目标方法
7.2 动态代理
-
public class OrderServiceDynamicProxy implements InvocationHandler private Object target; public OrderServiceDynamicProxy(Object obj) this.target = obj; /** 生成代理对象 */ public Object getTarget() Class<?> clz = target.getClass(); return Proxy.newProxyInstance(clz.getClassLoader(), clz.getInterfaces(), this); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable Object arg = args[0]; beforeProxy(arg); // 增强目标方法 Object object = method.invoke(target,arg); afterProxy(); return object; public void beforeProxy(Object obj) System.out.println("动态代理before"); int userId = 0; if (obj instanceof Order) Order order = (Order) obj; userId = order.getUserId(); int dbNum = userId % 2; System.out.println("动态代理分配到【db" + dbNum + "】处理数据"); // 设置分配的数据库 DataSourceContentHolder.setDBType("db" + dbNum); public void afterProxy() System.out.println("动态代理after");
-
测试方法
public class TestDynamicProxy
public static void main(String[] args)
Order order = new Order();
order.setUserId(2);
IOrderService dynamicProxy = (IOrderService) new OrderServiceDynamicProxy(new IOrderServiceImpl()).getTarget();
dynamicProxy.saveOrder(order);
- 请注意
// JDK中的代理只能对接口代理 否则会报错
IOrderServiceImpl dynamicProxy = (IOrderServiceImpl) new OrderServiceDynamicProxy(new IOrderServiceImpl()).getTarget();
有兴趣的可以手动debug一下这个代码~
7.3 Cglib代理
- 创建Cglib代理类
public class CglibProxy implements MethodInterceptor
public Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz)
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable
beforeProxy(o);
Object invoke = methodProxy.invokeSuper(o, objects);
afterProxy();
return invoke;
public void beforeProxy(Object obj)
System.out.println("Cglib动态代理before");
int userId = 0;
if (obj instanceof Order)
Order order = (Order) obj;
userId = order.getUserId();
int dbNum = userId % 2;
System.out.println("动态代理分配到【db" + dbNum + "】处理数据");
// 设置分配的数据库
DataSourceContentHolder.setDBType("db" + dbNum);
public void afterProxy()
System.out.println("动态代理after");
- 测试类
public class TestDynamicProxy
public static void main(String[] args)
Order order = new Order();
order.setUserId(2);
CglibProxy cglibProxy = new CglibProxy();
IOrderServiceImpl service = (IOrderServiceImpl) cglibProxy.getProxy(IOrderServiceImpl.class);
service.saveOrder(order);
- 输出
8.源码
Mybatis中的应用
-
MapperProxyFactory
-
代理模式
- 同时用到了享元模式(cachedMapperMethod(method))
以上是关于设计模式-代理模式的主要内容,如果未能解决你的问题,请参考以下文章
JUC并发编程 共享模式之工具 ThreadPoolExecutor 多线程设计模式 -- 异步模式之工作线程(定义饥饿 & 解决饥饿 & 线程池创建多少线程数目合适)