设计模式课程 设计模式精讲 16-2,3 代理模式Coding-静态代理-1
2024-09-06 23:19:04
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
最新文章
- 【代码笔记】iOS-点击加号增加书架,点击减号减少书架
- 你可能不知道的Google Chrome命令行参数
- MY_FIRSH_MODULE
- MATLAB代码加密生成.p文件
- log4j的ConversionPattern参数的格式含义-转
- SSH框架之Struts(2)——Struts的执行流程之配置文件
- ASP.NET 相同页面前后端之间传值
- CSS3学习--dispaly:inline和float:left两者区别
- php代码-1
- Android中的Audio播放:控制Audio输出通道切换
- win 8.1 安装 SQL server 遇到的各种问题
- java基础---->;java调用oracle存储过程(转)
- WP8关于对地图开发的改进
- shrio配置说明
- 如何获取Azure Storage Blob的MD5值
- Java 多线程并发编程之 Synchronized 关键字
- alpha-咸鱼冲刺day9
- oracle 11g 使用物化视图远程增量刷新数据
- css中 ~的作用
- _event_phase
热门文章
- vue基础笔记
- 【PAT甲级】1083 List Grades (25 分)
- 【Python与线程】
- 使用ssh 初始化git一个空java工程
- excel 练习玩具统计项目组excel日报
- QWidget::setLayout: Attempting to set QLayout ";"; on xxx ";";, which already has a layout
- Navicat连接远程主机(腾讯云服务器)的mysql失败,解决
- @ModelAttribute与@RequestBody的区别
- vs2013设置不生成.sdf和ipch文件
- I/O-<;文件读写、输出>;