可以理解为房东和中介的关系:
静态代理就是在代码中显示指定的代理;
动态代理无法代理类,但是可以代理接口;
在使用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 IOrderDao { int insert(Order order);}
public class OrderDaoImpl implements IOrderDao { @Override public int insert(Order order) { System.out.println("Dao层添加order成功"); return 1; }}
public interface IOrderService { /** 保存订单,参数为订单对象,返回值为生效行数 */ int saveOrder(Order order);}
public class OrderServiceImpl implements IOrderService { private IOrderDao iOrderDao; @Override public int saveOrder(Order order) { /** Spring会自己注入,我们这里就直接new出来了 */ iOrderDao = new OrderDaoImpl(); System.out.println("Service调用Dao层添加Order层"); return iOrderDao.insert(order); }}
有一个ThreadLocal:
public class DataSourceContextHolder { private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>(); public static void setDBType(String dbType) { CONTEXT_HOLDER.set(dbType); } public static String getDBType() { return (String)CONTEXT_HOLDER.get(); } public static void clearDBType() { CONTEXT_HOLDER.remove(); }}
Spring里面的分库:
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDBType(); }}
还有一个静态代理类:
public class OrderServiceStaticProxy { /** 在代理类里面注入目标对象 */ private IOrderService iOrderService; /** 我们要在这静态代理类里面增强这个方法 */ public int saveOrder(Order order){ beforeMethod(); /** 如果这里有spring容器的话,就不用显示的new了 */ iOrderService = new OrderServiceImpl(); int userId = order.getUserId(); /** 这里就是实现一个分库的功能,对userId取模2,这里就只会得到0或者是1 */ int dbRouter = userId % 2; System.out.println("静态代理分配到【db"+dbRouter+"】处理数据"); //todo 设置dataSource; DataSourceContextHolder.setDBType(String.valueOf(dbRouter)); afterMethod(); return iOrderService.saveOrder(order); } /** 我们要增强,我们就来写上一个before和after */ private void beforeMethod(){ System.out.println("静态代理 before code"); } private void afterMethod(){ System.out.println("静态代理 after code"); }}
测试代码如下:
public class Test { public static void main(String[]args){ Order order = new Order(); order.setUserId(1); /** 这里没有采用spring自动注入的方式,而是采用了直接new的方式 */ OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy(); orderServiceStaticProxy.saveOrder(order); }}
执行结果:
静态代理 before code
静态代理分配到【db1】处理数据
静态代理 after code
Service调用Dao层添加Order层
Dao层添加order成功
当我们把id改成2的时候:
public class Test { public static void main(String[]args){ Order order = new Order(); order.setUserId(2); /** 这里没有采用spring自动注入的方式,而是采用了直接new的方式 */ OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy(); orderServiceStaticProxy.saveOrder(order); }}
执行结果如下:
静态代理 before code
静态代理分配到【db0】处理数据
静态代理 after code
Service调用Dao层添加Order层
Dao层添加order成功
和我们的预期是一样的,这就实现了一个分库的功能;
这个就是一个动态代理的类:
public class OrderServiceDynamicProxy implements InvocationHandler { /** 这是目标类 */ private Object target; /** 通过构造器把目标类注入进来 */ public OrderServiceDynamicProxy(Object target) { this.target = target; } /** 进行绑定 */ public Object bind() { Class 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; } public void beforeMethod(Object obj) { int userId = 0; System.out.println("动态代理before code"); if (obj instanceof Order) { Order order = (Order) obj; userId = order.getUserId(); } /** 这里就是实现一个分库的功能,对userId取模2,这里就只会得到0或者是1 */ int dbRouter = userId % 2; System.out.println("动态代理分配到【db"+dbRouter+"】处理数据"); //todo 设置dataSource; DataSourceContextHolder.setDBType(String.valueOf(dbRouter)); } public void afterMethod() { System.out.println("动态代理after core"); }}
我们来写一个测试类:
public class Test { public static void main(String[]args){ Order order = new Order(); order.setUserId(2); /** 这里没有采用spring自动注入的方式,而是采用了直接new的方式 */ IOrderService orderServiceDynamicProxy = (IOrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind(); orderServiceDynamicProxy.saveOrder(order); }}
执行结果:
动态代理before code
动态代理分配到【db0】处理数据
Service调用Dao层添加Order层
Dao层添加order成功
动态代理after core
而当我们把id改成1的时候:
public class Test { public static void main(String[]args){ Order order = new Order(); order.setUserId(1); /** 这里没有采用spring自动注入的方式,而是采用了直接new的方式 */ IOrderService orderServiceDynamicProxy = (IOrderService) new OrderServiceDynamicProxy(new OrderServiceImpl()).bind(); orderServiceDynamicProxy.saveOrder(order); }}
分到了db1的这个库里面:
执行结果:
动态代理before code
动态代理分配到【db1】处理数据
Service调用Dao层添加Order层
Dao层添加order成功
动态代理after core
联系客服