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. 2000G电脑大型单机游戏合集

    激活码 游戏名称(ctrl+F查找) 下载链接005875 艾迪芬奇的记忆 游戏下载链接http://pan.baidu.com/s/1t2PYRAj546_1AcOB-khJZg554158 暗影: ...

  2. 【C语言】创建一个函数,判断某一正整数是否为素数,并调用这个函数找出1000以内所有素数

    #include <stdio.h> int fun(int x) { int n; ;n<=x-;n++) ) break; if(n>=x) ; else ; } main ...

  3. pdf .js和tableexport.js使用时遇到的2问题。

    pdf .js 问题一:报错 network.js:71 The provided value 'moz-chunked-arraybuffer' is not a valid enum value  ...

  4. Django 删除 migrations

    如果想重新创建表格,可以按如下步骤进行操作: 1. 从数据库中删除表格 DROP TABLE `table_name`; 2. 删除 migrations 文件 文件在APP名称下的 migratio ...

  5. WORKDIR 指定工作目录 每一个 RUN 都是启动一个容器、执行命令、然后提交存储层文件变更

    WORKDIR 指定工作目录 格式为 WORKDIR <工作目录路径>. 使用 WORKDIR 指令可以来指定工作目录(或者称为当前目录),以后各层的当前目录就被改为指定的目录,如该目录不 ...

  6. Codeforces Round #589 (Div. 2)D(思维,构造)

    #define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;vector<int>adj[10 ...

  7. 【PAT甲级】1046 Shortest Distance (20 分)

    题意: 输入一个正整数N(<=1e5),代表出口的数量,接下来输入N个正整数表示当前出口到下一个出口的距离.接着输入一个正整数M(<=10000),代表询问的次数,每次询问输入两个出口的序 ...

  8. 洛谷 P5057 [CQOI2006]简单题(树状数组)

    嗯... 题目链接:https://www.luogu.org/problem/P5057 首先发现这道题中只有0和1,所以肯定与二进制有关.然后发现这道题需要支持区间更改和单点查询操作,所以首先想到 ...

  9. jmeter 并发控制

    1.吞吐控制器以线程组的请求sampler为控制对象, 2.事务控制器: 3.同步定时器syn timer:对某线程组下任意的sampler任意位置作用为,有序控制单个sampler的并发先sampl ...

  10. nginx windows下重新加载配置

    运行过程中,有个节点部分服务出现故障,像将其下线修复, 使用nginx -t; nginx -s reload 重新加载配置 得到错误"nginx: [error] OpenEvent(&q ...