1    代码演练

1.1  代码演练1(静态代理之分库操作)

1    代码演练
1.1  代码演练1(静态代理之分库操作)

需求:

订单管理,模拟前置后置方法,模拟分库管理

重点:

重点看订单静态代理,动态数据源和分库操作上下文。

UML类图:

测试类:

package com.geely.design.pattern.structural.proxy;

import com.geely.design.pattern.structural.proxy.staticProxy.OrderServiceStaticProxy;

public class Test {

    public static void main(String [] args){
Order order = new Order();
order.setUserID(1);
OrderServiceStaticProxy orderServiceStaticProxy = new OrderServiceStaticProxy();
orderServiceStaticProxy.saveOrder(order); order.setUserID(2);
orderServiceStaticProxy.saveOrder(order); }
}

订单类:

package com.geely.design.pattern.structural.proxy;

/**
* 建立订单实体类
*/
public class Order {
private Object orderInfo;
//之所以选择integer类型,是为了方便OrderServiceStaticProxy静态代理类进行分库
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;
}
}

订单dao:

package com.geely.design.pattern.structural.proxy;

public interface IOrderDao {
int insertOrder(Order order);
}

订单daoIMPL:

package com.geely.design.pattern.structural.proxy;

public class OrderDaoImpl implements IOrderDao{
@Override
public int insertOrder(Order order) {
System.out.println("新增一条订单!");
return 1;
}
}

订单Service:

package com.geely.design.pattern.structural.proxy;

public interface IOrderService {
int saveOrder(Order order);
}

订单ServiceIMPL:

package com.geely.design.pattern.structural.proxy;

public class OrderServiceImpl implements IOrderService {
private IOrderDao orderDao; @Override
public int saveOrder(Order order) {
//Spring会自己注入,这里我们直接new了
orderDao = new OrderDaoImpl();
System.out.println("Service层调用dao层添加Order");
return orderDao.insertOrder(order);
}
}

订单静态代理:

package com.geely.design.pattern.structural.proxy.staticProxy;

import com.geely.design.pattern.structural.proxy.IOrderService;
import com.geely.design.pattern.structural.proxy.Order;
import com.geely.design.pattern.structural.proxy.OrderServiceImpl;
import com.geely.design.pattern.structural.proxy.db.DataSourceContextHolder; public class OrderServiceStaticProxy {
private IOrderService orderService; /**
* 添加前置方法和后置方法
* @param order
* @return
*/
public int saveOrder(Order order){
beforeMethod();
//spring中会注入,这里我new一下
orderService = new OrderServiceImpl(); /**
* 这里添加分库方法,根据user取模,根据余数进行分库
*/
int userID = order.getUserID();
int dbRouter = userID%2;
//todo设置datasource,记住,dbType一定要和我们xml中配置的key相同
DataSourceContextHolder.setDBType("db"+String.valueOf(dbRouter)); System.out.println("静态代理分配到 【db"+dbRouter+"】数据库进行处理数据!");
int a = orderService.saveOrder(order);
afterMethod();
return a;
}
/**
* 这里参照spring aop的做法,增加了前置通知方法 方法的增强
*/
private void beforeMethod(){
System.out.println("静态代理 前置方法");
} /**
* 这里参照spring aop的做法,增加了后置通知方法  方法的增强
*/
private void afterMethod(){
System.out.println("静态代理 后置方法");
}
}

动态数据源:

package com.geely.design.pattern.structural.proxy.db;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
* 分库操作:该类为动态数据源类
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDBType();
} /**
* 如果是在spring中开发,ioc.xml中
*/
// <bean id="db0" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
// <property name="driverClassName" value="${db.driverClassName}"/>
// <property name="url" value="${db.url}"/>
// <property name="username" value="${db.username}"/>
// <property name="password" value="${db.password}"/>
// <!-- 连接池启动时的初始值 -->
// <property name="initialSize" value="${db.initialSize}"/>
// <!-- 连接池的最大值 -->
// <property name="maxActive" value="${db.maxActive}"/>
// <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
// <property name="maxIdle" value="${db.maxIdle}"/>
// <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
// <property name="minIdle" value="${db.minIdle}"/>
// <!-- 最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制 -->
// <property name="maxWait" value="${db.maxWait}"/>
// <!--#给出一条简单的sql语句进行验证 -->
// <!--<property name="validationQuery" value="select getdate()" />-->
// <property name="defaultAutoCommit" value="${db.defaultAutoCommit}"/>
// <!-- 回收被遗弃的(一般是忘了释放的)数据库连接到连接池中 -->
// <!--<property name="removeAbandoned" value="true" />-->
// <!-- 数据库连接过多长时间不用将被视为被遗弃而收回连接池中 -->
// <!--<property name="removeAbandonedTimeout" value="120" />-->
// <!-- #连接的超时时间,默认为半小时。 -->
// <property name="minEvictableIdleTimeMillis" value="${db.minEvictableIdleTimeMillis}"/>
//
// <!--# 失效检查线程运行时间间隔,要小于MySQL默认-->
// <property name="timeBetweenEvictionRunsMillis" value="40000"/>
// <!--# 检查连接是否有效-->
// <property name="testWhileIdle" value="true"/>
// <!--# 检查连接有效性的SQL语句-->
// <property name="validationQuery" value="SELECT 1 FROM dual"/>
// </bean> // <bean id="db1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
// <property name="driverClassName" value="${db.driverClassName}"/>
// <property name="url" value="${db.url}"/>
// <property name="username" value="${db.username}"/>
// <property name="password" value="${db.password}"/>
// <!-- 连接池启动时的初始值 -->
// <property name="initialSize" value="${db.initialSize}"/>
// <!-- 连接池的最大值 -->
// <property name="maxActive" value="${db.maxActive}"/>
// <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
// <property name="maxIdle" value="${db.maxIdle}"/>
// <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
// <property name="minIdle" value="${db.minIdle}"/>
// <!-- 最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制 -->
// <property name="maxWait" value="${db.maxWait}"/>
// <!--#给出一条简单的sql语句进行验证 -->
// <!--<property name="validationQuery" value="select getdate()" />-->
// <property name="defaultAutoCommit" value="${db.defaultAutoCommit}"/>
// <!-- 回收被遗弃的(一般是忘了释放的)数据库连接到连接池中 -->
// <!--<property name="removeAbandoned" value="true" />-->
// <!-- 数据库连接过多长时间不用将被视为被遗弃而收回连接池中 -->
// <!--<property name="removeAbandonedTimeout" value="120" />-->
// <!-- #连接的超时时间,默认为半小时。 -->
// <property name="minEvictableIdleTimeMillis" value="${db.minEvictableIdleTimeMillis}"/>
//
// <!--# 失效检查线程运行时间间隔,要小于MySQL默认-->
// <property name="timeBetweenEvictionRunsMillis" value="40000"/>
// <!--# 检查连接是否有效-->
// <property name="testWhileIdle" value="true"/>
// <!--# 检查连接有效性的SQL语句-->
// <property name="validationQuery" value="SELECT 1 FROM dual"/>
// </bean> /**
* 这个是在spring中的db的具体的配置
*
* 如果我们不指定,默认的是db0beanId
*/
// <bean id="dataSource" class="com.geely.design.pattern.structural.proxy.db.DynamicDataSource">
// <property name="targetDataSources">
// <map key-type="java.lang.String">
// <entry value-ref="db0" key="db0"></entry>
// <entry value-ref="db1" key="db1"></entry>
// </map>
// </property>
// <property name="defaultTargetDataSource" ref="db0"></property>
// </bean> // <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
// <property name="dataSource" ref="dataSource" />
// </bean>
}

分库操作上下文:

package com.geely.design.pattern.structural.proxy.db;

/**
* 分库操作:
* dbRouter上下文类 ,在执行dao层之前,如果我们设置了 setDBType设置了dbType为db1 或者 db0,dao层就会去连接对应的数据库。
* db0和db1就是Spring容器中我们配置的beanID
*/
public class DataSourceContextHolder {
//该变量可以存放dataSource的beanName
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<String>(); public static void setDBType(String dbType){
CONTEXT_HOLDER.set(dbType);
} public static void clearDBType(String dbType){
CONTEXT_HOLDER.remove();
} public static String getDBType(){
return (String) CONTEXT_HOLDER.get();
}
}

打印结果:

Connected to the target VM, address: '127.0.0.1:8341', transport: 'socket'
静态代理 前置方法
静态代理分配到 【db1】数据库进行处理数据!
Service层调用dao层添加Order
新增一条订单!
静态代理 后置方法
静态代理 前置方法
静态代理分配到 【db0】数据库进行处理数据!
Service层调用dao层添加Order
新增一条订单!
静态代理 后置方法
Disconnected from the target VM, address: '127.0.0.1:8341', transport: 'socket' Process finished with exit code 0

最新文章

  1. 【代码笔记】iOS-点击加号增加书架,点击减号减少书架
  2. 你可能不知道的Google Chrome命令行参数
  3. MY_FIRSH_MODULE
  4. MATLAB代码加密生成.p文件
  5. log4j的ConversionPattern参数的格式含义-转
  6. SSH框架之Struts(2)——Struts的执行流程之配置文件
  7. ASP.NET 相同页面前后端之间传值
  8. CSS3学习--dispaly:inline和float:left两者区别
  9. php代码-1
  10. Android中的Audio播放:控制Audio输出通道切换
  11. win 8.1 安装 SQL server 遇到的各种问题
  12. java基础----&gt;java调用oracle存储过程(转)
  13. WP8关于对地图开发的改进
  14. shrio配置说明
  15. 如何获取Azure Storage Blob的MD5值
  16. Java 多线程并发编程之 Synchronized 关键字
  17. alpha-咸鱼冲刺day9
  18. oracle 11g 使用物化视图远程增量刷新数据
  19. css中 ~的作用
  20. _event_phase

热门文章

  1. vue基础笔记
  2. 【PAT甲级】1083 List Grades (25 分)
  3. 【Python与线程】
  4. 使用ssh 初始化git一个空java工程
  5. excel 练习玩具统计项目组excel日报
  6. QWidget::setLayout: Attempting to set QLayout &quot;&quot; on xxx &quot;&quot;, which already has a layout
  7. Navicat连接远程主机(腾讯云服务器)的mysql失败,解决
  8. @ModelAttribute与@RequestBody的区别
  9. vs2013设置不生成.sdf和ipch文件
  10. I/O-&lt;文件读写、输出&gt;