【设计模式】代理模式实现连接池

1. 连接池

创建Connection的过程是非常耗时的,为了保证Conection可以重用。应该将Connection进行池管理。

使用静态工厂方法管理一个唯一的连接:

/**
 * 用静态工厂方法管理一个唯一的可重用的连接
 */
public class ConnUtils {
    private ConnUtils(){}
    private static Connection con;
    //在静态代码块中创建与数据库的连接
    static{
       try{
           Class.forName("com.mysql.jdbc.Driver");
           String url = "jdbc:mysql:///db_test?characterEncoding=UTf8";
           con = DriverManager.getConnection(url,"root","root");
       }catch(Exception e){
           throw new RuntimeException(e.getMessage(),e);
       }
    }
    //使用静态工厂方法,返回connection实例
    public static Connection getCon(){[W1]
       return con;
    }
}

2. 连接池的实现

为什么要有连接池?

1. 维护多个连接。必须要保证每一个线程获取到的是不同的connection对象。

2. 提供一个方法可以回收连接。

以下是最基本的实现:

public class ConnUtils2 {
    //声明一个容器,放所有声明的连接Connection
    private static List<Connection> pool = new ArrayList<Connection>();
    static{
       try{
           Class.forName("com.mysql.jdbc.Driver");
           String url = "jdbc:mysql:///db_test?characterEncoding=UTf8";
           for(int i=0;i<3;i++){
              //创建三个连接
              Connection con = DriverManager.getConnection(url,"root","root");
              //将这个三个连接放到pool中去
              pool.add(con);
           }
           System.err.println("连接:"+pool);
       }catch(Exception e){
           throw new RuntimeException(e.getMessage(),e);
       }
    }
    public static Connection getCon(){
       synchronized (pool) {
           Connection con = pool.remove(0);
           try {
              Thread.sleep(100);
           } catch (InterruptedException e) {
              e.printStackTrace();
           }
           System.err.println("还有:"+pool.size());
           return con;
       }
    }
    //手工还连接 – close
    public static void back(Connection con){
       System.err.println("还连接:"+con);
       pool.add(con);
    }
}

实际中总是调用close方法,所以为了回收连接。我们应该重写close方法。对close方法增强。可以使用以下三种方式进行方法增强:子类,包装,代理。

3. 在代码中调用close时也可以还连接,对close方法进行修改。

动态代理作用:

1. 对某个方法增强。

2. 在不污染源类的情况下,修改原类的行为。

代理类,与被代理类,两个不同的实体。

要求:

所有被代理的类,都必须要实现同一个接口。

本质上是对方法进行修改,但其实它是通过反射执行的某个方法。

4. 动态代理的核心类

Proxy – 用于创建给定接口的子类,在内存中动态的创建。$Proxy0.此类只使用一次。

InovocationHandler – 执行句柄。在执行时可以获取被代理类的所有反射。用户的每一次调用都会被这个句柄拦截到。

5. 代理的任务

1. 在内存中创建某个接口的子类。

2. 拦截所有在代理上执行的方法。(除了getClass方法)

6. 用动态代理书写连接池

代理的目标:原生的connection。

代理的目的:修改close方法,让close方法不可以关闭连接,且主动收回连接。

通过动态代理,和线程通讯:

1. 对Connection进行代理。

2. 在获取Connection时,通过同步,如果没有连接时,就让线程进入等待池。

3. 修改close方法,且在还了连接以后唤醒正在等待的线程。

public class ConnUtils3 {
    //声明连接池维护所有的连接
    private static List<Connection> pool = new ArrayList<Connection>();
    //静态代码块中创建多个连接
    static{
       try{
           Class.forName("com.mysql.jdbc.Driver");
           String url = "jdbc:mysql:///db_test?characterEncoding=UTF8";
           for(int i=0;i<3;i++){
              final Connection con = DriverManager.getConnection(url,"root","root");
              //对con对象进行动态代理
              Object proxyedCon =
                     Proxy.newProxyInstance(
                            ConnUtils3.class.getClassLoader(),
                            new Class[]{Connection.class},
                            //声明执行句柄,只对close方法设置拦截
                            new InvocationHandler() {
                                public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
                                   if(method.getName().equals("close")){
                                       System.err.println("想关闭连接,不能关,还连接");
                                       //将proxy再加到pool中,这个proxy就是proxyedCon
                                       synchronized (pool) {
                                          pool.add((Connection) proxy);
                                          pool.notify();
                                       }
                                       return null;
                                   }else{
                                       System.err.println("放行"+method.getName());
                                       return method.invoke(con, args);  // 通过反射执行被代理对象的方法
                                    }
                                }
                            });
              //将代理对象添加到池中
              pool.add((Connection) proxyedCon);
           }
       }catch(Exception e){
           throw new RuntimeException(e.getMessage(),e);
       }
    }
    /**
     * 提供一个静态工厂方法返回一个连接
     */
    public static Connection getCon(){
       synchronized (pool) {
           if(pool.size()==0){
              try {
                  pool.wait();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              return getCon();
           }
           Connection con = pool.remove(0);//返回一个代理的connection对象
           System.err.println("还有几个:"+pool.size());
           return con;
       }
    }
}

7. 再说连接池的作用

1. 维护多个连接。

在初始化时创建List,将多个连接放到List中去.

2. 可以在close时回收连接

对Connection进行动态代理,

对close方法进行拦截。

Author:顾故

Sign:别输给曾经的自己

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-03 22:04:40

【设计模式】代理模式实现连接池的相关文章

23种设计模式----------代理模式(三) 之 动态代理模式

(上一篇)种设计模式----------代理模式(二) 当然代理模式中,用的最广泛的,用的最多的是  动态代理模式. 动态代理:就是实现阶段不用关系代理是哪个,而在运行阶段指定具体哪个代理. 抽象接口的类图如下: --图来自设计模式之禅 所以动态代理模式要有一个InvocationHandler接口 和 GamePlayerIH实现类.其中 InvocationHandler是JD提供的动态代理接口,对被代理类的方法进行代理. 代码实现如下 抽象主题类或者接口: 1 package com.ye

设计模式 - 代理模式(proxy pattern) 未使用代理模式 详解

代理模式(proxy pattern) 未使用代理模式 详解 本文地址: http://blog.csdn.net/caroline_wendy 部分代码参考: http://blog.csdn.net/caroline_wendy/article/details/37698747 如果需要监控(monitor)类的某些状态, 则需要编写一个监控类, 并同过监控类进行监控. 但仅仅局限于本地, 如果需要远程监控, 则需要使用代理模式(proxy pattern). 具体方法: 1. 类中需要提供

设计模式——代理模式

概念 代理模式(Proxy),为其他对象提供一种代理以控制对象的访问. 模式结构 一个是真正的你要访问的对象(目标类),一个是代理对象,真正对象与代理对象实现同一个接口,先访问代理类再 访问真正要访问的对象. 代理模式UML图 代码实战 <span style="font-family:KaiTi_GB2312;font-size:18px;"> //代理模式 class  Proxy : IGiveGift                   //让"代理&qu

23种设计模式----------代理模式(二)

(上一篇)23种设计模式----------代理模式(一) 之前说了基本的代理模式和普通代理模式.接下来开始看下强制代理模式和虚拟代理模式 三,强制代理模式: 一般的代理模式都是通过代理类找到被代理的对象,从而调用被代理类中的方法(即完成被代理类中的任务). 而,强制代理模式则是先找到被代理类自己去完成事情,然后被代理类又将该做的事情转交到代理类中,让代理类来完成. 假如:你有事求助于某位名人. 你告诉名人说有事想请他帮忙,然后他说最近一段时间比较忙,要不你找我的经纪人来办吧. (本来找名人办事

23种设计模式----------代理模式(一)

代理模式也叫委托模式. 代理模式定义:对其他对象提供一种代理从而控制对这个对象的访问.就是,代理类 代理 被代理类,来执行被代理类里的方法. 一般情况下,代理模式化有三个角色. 1,抽象的主题类(或者接口) IGamePlayer 2,代理类. 3,被代理类. 下面以游戏玩家代理为例. 一,先来看下最基本的代理模式. 代码如下: 主题接口: 1 package com.yemaozi.proxy.base; 2 3 //游戏玩家主题接口 4 public interface IGamePlaye

5.大话设计模式-代理模式

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DesignModel { public class Proxy:IAction { ZQZ zzz = null; public Proxy(ZQZ mm) { zzz = mm; } public void SendFlower() { zzz

设计模式----代理模式(Proxy)

为还有一个对象提供一个替身或占位符以控制对这个对象的訪问. 代理模式的组成: 主题接口(Subject):提取真正主题与代理的公共方法,让使用真正主题的地方也能用代理取代. 真正主题(RealSubject):真正处理请求的类. 代理(Proxy):真正主题的代理类,请求方通过调用代理对象间接调用真正主题. 代理模式的简单样例: (主题接口类)Subject.java package xu.neng.Proxy; public interface Subject { public void re

一起学java设计模式--代理模式(结构型模式)

代理模式 应用软件所提供的桌面快捷方式是快速启动应用程序的代理,桌面快捷方式一般使用一张小图片来表示(Picture),通过调用快捷方式的run()方法将调用应用软件(Application)的run()方法.使用代理模式模拟该过程,绘制类图并编程实现. package ProxyPattern; interface Software { void run(); } class Application implements Software { public void run() { Syste

设计模式-代理模式(Go语言描述)

大家好, 我是大帅哥,由于最近又变帅了, 所以我决定由我的代理人小帅哥来写这篇博客,不过内容可以放心,还是由我来完成,小帅哥的活就是将我的内容替我发出来罢了. &_& 还是进入正题吧, 今天这篇博客我们继续来学习设计模式, 在学习了上面几个设计模式之后大家有没有发现设计模式其实很简单, 难道地方是何时选用合适的模式, 这也是设计模式最重要的地方, 不能我们学会的设计模式就可以乱用. 明白就好-- 下面我们就开始介绍一个新的设计模式-代理模式. 模式定义 什么是代码模式? 其实文章刚开始的段