代理模式应用场景:
生活中的租房中介、售票黄牛、婚介、经纪人、快递、事物代理、非侵入式日志监听等,都属于是代理模式的实际体现、代理模式(proxy Pattern)的定义也非常简单,是指为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间祈祷中介作用,代理式属于结构型设计模式。使用代理主要由两个目的:一是保护目标对象,二是增强目标对象。
静态代理
在分布式业务场景中,通常会对数据库进行分库分表,分库分表之后使用 Java 操作时就可能需要配置多个数据源,我们通过设置数据源路由来动态切换数据源。先创建 Order 订单类:
@Data public class Order { private Object orderInfo; private Long createTime; private String id; }
创建OrderDao 持久层操作类:
public class OrderDao { public int insert(Order order){ System.out.println("OrderDao 创建 order 成功!"); return 1; } }
创建 IOrderService 接口:
public class OrderService implements IOrderService { private OrderDao orderDao; public OrderService(){ //如果使用spring是自动注入的 //为了使用方便,在构造方法中将orderDao直接初始化 orderDao = new OrderDao(); } @Override public int createOrder(Order order) { System.out.println("OrderService 调用 OrderDao 闯将订单"); return orderDao.insert(order); } }
接下来使用动态代理,主要完成的功能时:根据订单创建时间自动按年份进行分库。根据开闭原则,修改原来写好的代码逻辑,通过代理对象来完成。先创建数据源路由对象,使用 ThreadLocal 的单例事项 DynamicDataSourceEntry 类:
package com.xq.design.proxy.staticproxy.dbroute.db; //动态切换数据源 public class DynamicDataSourceEntry { //默认数据源 public final static String DEFAULT_SOURCE = null; private final static ThreadLocal<String> local = new ThreadLocal<String>(); private DynamicDataSourceEntry(){} //清空数据源 public static void clear(){ local.remove(); } //获取当前正在使用的数据源名字 public static String get(){ return local.get(); } //还原当前切换的数据源 public static void restore(){ local.set(DEFAULT_SOURCE); } //设置已知名字的数据源 public static void set(String source){ local.set(source); } //根据年份动态设置数据源 public static void set(int year){ local.set("DB_" + year); } }
创建切换数据源的代理类 OrderServiceStaticProxy:
package com.xq.design.proxy.staticproxy.dbroute.proxy; import com.xq.design.proxy.staticproxy.IOrderService; import com.xq.design.proxy.staticproxy.Order; import com.xq.design.proxy.staticproxy.dbroute.db.DynamicDataSourceEntry; import java.text.SimpleDateFormat; import java.util.Date; public class OrderServiceStaticProxy implements IOrderService { private SimpleDateFormat yearFormat = new SimpleDateFormat("yyyy"); private IOrderService orderService; public OrderServiceStaticProxy(IOrderService orderService){ this.orderService = orderService; } @Override public int createOrder(Order order) { before(); Long time = order.getCreateTime(); Integer dbRouter = Integer.valueOf(yearFormat.format(new Date(time))); System.out.println("静态代理类自动分配到【DB_" + dbRouter + "】数据源处理数据"); DynamicDataSourceEntry.set(dbRouter); orderService.createOrder(order); after(); return 0; } private void before(){ System.out.println("Proxy before method."); } private void after(){ System.out.println("Proxy after method."); } }
测试代码如下:
@Test void test(){ try{ Order order = new Order(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); Date date = sdf.parse("2020/05/10"); order.setCreateTime(date.getTime()); IOrderService orderService = new OrderServiceStaticProxy(new OrderService()); orderService.createOrder(order); } catch (Exception e){ e.printStackTrace(); } }
运行结果如下: