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

设计模式课程 设计模式精讲 16-2,3 代理模式Coding-静态代理-1的更多相关文章

  1. Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景

    我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...

  2. Java设计模式-代理模式之动态代理(附源代码分析)

    Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...

  3. 设计模式课程 设计模式精讲 7-2 建造者模式Coding

    1 代码演练 1.1 建造者模式演练 1.2 静态内部类演练建造者模式(链式调用) 1 代码演练 1.1 建造者模式演练 需求: 根据讲师提供的课程名称,课程ppt,课程视频,课程手记,课程问答 制作 ...

  4. 设计模式课程 设计模式精讲 17-2 模板方法模式coding

    1 代码演练 1.1 代码演练1 1.2 代码演练2(后端课程子类运用钩子方法,加入写手记的方法) 1.3 代码演练3(前端有多个子类,有得需要写手记,有得不需要写,如何实现?) 1 代码演练 1.1 ...

  5. 《Java设计模式》之代理模式 -Java动态代理(InvocationHandler) -简单实现

    如题 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式可细分为如下, 本文不做多余解释 远程代理 虚拟代理 缓冲代理 保护代理 借鉴文章 ht ...

  6. 设计模式课程 设计模式精讲 6-2 抽象工厂coding

    1 代码讲解 1.1 抽象工厂优点 1.2 抽象工厂缺点 1.3 为何有产品族的业务场景宜用抽象工厂设计模式?而不是工厂设计模式? 2 代码演练 2.1 抽象工厂代码演练 1 代码讲解 1.1 抽象工 ...

  7. 设计模式课程 设计模式精讲 18-2 迭代器模式coding

    1 代码演练 1.1 代码演练1(迭代器模式演练) 1.2 代码使用场景 1 代码演练 1.1 代码演练1(迭代器模式演练) 需求: 课程管理:需要实现课程可进行增添,删除,并能够打印出课程列表. u ...

  8. 设计模式课程 设计模式精讲 5-2 工厂方法coding

    1 课堂讲义 1.1 产品等级和产品簇 2 代码演练 2.1 工厂方法代码演练 1 课堂讲义 1.1 产品等级和产品簇 工厂方法是为了解决同一产品等级的业务抽象问题 抽象工厂方法是为了解决同一产品簇的 ...

  9. 设计模式课程 设计模式精讲 22-2 备忘录模式coding

    1 代码演练 1.1 代码演练1 1 代码演练 1.1 代码演练1 需求: 网站笔记需要存储快照,能实现回退的功能. 注意: a 设计的时候,可以分为笔记类,笔记快照类和 笔记快照管理类  三个类. ...

  10. 设计模式课程 设计模式精讲 2-3 UML类图讲解自上而下

    1 内容简析(易错加粗) 2 uml类图展示 1 内容简析(易错加粗) 1.1 设计模式中的对象关系 依赖关系 虚线箭头 组合关系 实心菱形 聚合关系 空心菱形(想象成盘子,盛东西,盘子的多,另一方少 ...

随机推荐

  1. window下进程退出后自动重启

    设计思想:编写批处理脚本监控进程的运行状态,如果发现进程停止,则自动重启该进程.批处理脚本(jk.bat)和进程脚本(hello.bat)如下: 1.jk.bat @echo off rem 定义需监 ...

  2. 微信小程序中promise的使用

    简介 相信看到这篇文章的同学,都已经对微信小程序的api文档有所了解了,也都经历了微信小程序api回调函数嵌套的痛苦,才会想要通过Promise解决回调地狱这个问题,我下面就直接介绍怎么在小程序中使用 ...

  3. 【Go语言系列】1.4、GO语言简介:第一个Go语言程序

    接下来我们来编写第一个 Go 程序 hello.go(Go 语言源文件的扩展是 .go),代码如下: // 声明 main 包 package main import ( "fmt" ...

  4. JavaScript - 代码片段,Snippets,Gist

    求n个数字的累加和 递归实现 function getSum(x) { if (x == 1) { return 1; } return x + getSum(x - 1); } var result ...

  5. 实现简单HttpServer案例

    <html> <head> <title>第一个表单</title> </head> <body> <pre> me ...

  6. springmvc项目的搭建

    springmvc替代servlet的工作 Servlet - Springmvc        jsp ->Servlet (Springmvc)->Jsp springmvc配置文件 ...

  7. keytool生成keystore

    在密钥库中生成本地数字证书:需要提供身份.加密算法.有效期等信息:keytool指令如下,产生的本地证书后缀名为:*.keystore keytool -genkeypair -keyalg RSA ...

  8. 吴裕雄--天生自然TensorFlow2教程:反向传播算法

  9. 01-JAVA语言基础(动手动脑)

    一.一个JAVA类文件中只能有一个public类吗? 01-JAVA语言基础.ppt第22页“一个Java源文件中可以写多个类,但其中只能有一个类是“公有(public)”的,并且Java要求源文件名 ...

  10. Redis 简易消息队列

    为了保持程序的高效,建议使用ProtoBuf. Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48, ...