总结代理模式 并根据数据库连接池原理来模拟实现自己的数据库连接池工具类

代理模式

需求:对系统中已有的某个类的功能,进行扩展(增强)

要求:在不修改源码的情况下,对已有的功能进行增强

静态代理

抽象接口:保证包含增强功能的对象和原有功能的对象,对外提供相同的方法

目标对象:封装了原有功能

代理对象:封装了增强功能和原有功能(通过持有一个目标对象的引用实现)

问题:代码不够灵活,产生大量冗余工作

动态代理

动态代理的实现API:

Proxy :

帮助程员产生代理对象,提供产生代理类和代理对象的静态方法

InvocationHandler :

句柄接口,拦截到,所有代理对象调用的方法(所有代理对象调用的方法,都可以被

InvocationHandler拦截到)

模拟实现数据库连接池

数据库的操作:考虑性能问题

频繁的连接和断开数据,本身很消耗资源(操作数据的性能)

---对数据库连接对象,进行池管理(由池中获得资源,用完之后将资源再次放入)

连接池的具体实现:

1 创建一个集合对象,封装n个Connection对象

2 定义获得连接

3 和归还连接的功能

实现代码:

 1 public class DBPoolUtils {
 2     private static String driver;
 3     private static String url;
 4     private static String username;
 5     private static String password;
 6     private static int maxconn;//线程池最大的连接数
 7
 8     //定义一个集合表示线程池
 9     static List<Connection> list=new ArrayList<Connection>();
10     //类加载的时候就初始化,创建好连接对象
11     static{
12         Properties properties=new Properties();
13         try {
14             //读取配置文件信息
15             properties.load(DBPoolUtils.class.getResourceAsStream("mysql.properties"));
16             driver=properties.getProperty("driver");
17             url=properties.getProperty("url");
18             username=properties.getProperty("username");
19             password=properties.getProperty("password");
20             maxconn=Integer.parseInt(properties.getProperty("maxconn"));
21             Class.forName(driver);
22             /*
23              * 创建连接对象
24              * 因为当用户关闭的时候要把线程连接对象还到线程池中,
25              * 所有拿到的对象与还回来的对象都应该是代理对象。
26              * 对close()方法进行拦截,把原来断开连接改成将线程连接对象还到连接池
27              */
28             for (int i = 0; i < maxconn; i++) {
29                 final Connection conn=DriverManager.getConnection(url, username, password);
30                 //创建代理对象
31                 Object connProxy=Proxy.newProxyInstance(
32                         DBPoolUtils.class.getClassLoader(),//自定义类的类加载器
33                         new Class<?>[]{Connection.class},//实现的接口的class文件数组
34                         new InvocationHandler() {//匿名内部类实现InvocationHandler
35
36                             @Override
37                             public Object invoke(
38                                     Object proxy,//代理对象
39                                     Method method,//代理对象实现接口中调用的方法
40                                     Object[] args//代理对象实现接口中调用的方法中的参数
41                                     )throws Throwable {
42                                 //拦截close()方法,将原来的断开连接改为还回连接池,即:将当前的代理对象加到线程池中
43                                 String methodName=method.getName();
44                                 if ("close".equals(methodName)) {
45                                     list.add((Connection) proxy);
46                                     //唤醒等待的线程
47                                     synchronized (list) {
48                                         list.notifyAll();
49                                     }
50                                 }
51                                 //放行:调用原来的对象方法
52                                 Object obj=method.invoke(conn, args);
53                                 return obj;
54                             }
55                         });
56                 //将创建好的代理线程对象加线程池
57                 list.add((Connection) connProxy);
58             }
59         } catch (IOException e) {
60             e.printStackTrace();
61         } catch (ClassNotFoundException e) {
62             e.printStackTrace();
63         } catch (SQLException e) {
64             e.printStackTrace();
65         }
66     }
67     /**
68      * 对外提供一个连接对象
69      * @return
70      */
71     public static Connection getConnection(){
72         //当线程池中没有连接对象的时候,让线程等待,而不报异常,等待其他线程返回时再唤醒
73         synchronized (list) {
74             if (list.size()==0) {
75                 try {
76                     list.wait();
77                 } catch (InterruptedException e) {
78                     e.printStackTrace();
79                 }
80             }
81         }
82         //每次从线程池中取出第一个线程
83         Connection conn=list.remove(0);
84         System.out.println("剩余:"+list.size());
85         return conn;
86     }
87 }
时间: 2024-08-05 13:29:20

总结代理模式 并根据数据库连接池原理来模拟实现自己的数据库连接池工具类的相关文章

(二) 代理模式详解(包含原理详解)

转载:http://www.cnblogs.com/zuoxiaolong/p/pattern3.html 本章接着讨论第二种要介绍的设计模式,代理模式. LZ不希望写的东西与网络上的资料千篇一律,所以这一系列不会像很多典型文章一章,只是列出这个模式的定义以及一堆适用的情况,然后就是一堆这个模式的各个角色,对于这种罗列LZ并不反对,相比之下会比较清晰,但是如果脱离了实际,就会导致看的人特别是初学者觉得设计模式很陌生很遥远. LZ并不反对这种教学式的标准模式,但说实话,LZ本人看这种帖子从来都感觉

java并发包&amp;线程池原理分析&amp;锁的深度化

      java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问.数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中.当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制.移动.代价比较高.因此,它适合随机查找和遍历,不适合插入和删除. 2.Vector与Arra

代理模式 vs 装饰模式

代理模式和装饰模式有很大的相似性,二者的类图(几乎)是一样的.下面分别讲解代理模式和装饰模式. 1.代理模式 一般著名的跑步运动员都会有自己的代理人,如果想联系该运动员的比赛事宜,可以直接联系他的代理人就可以了.类图如下所示: IRunner接口如下: public interface IRunner { public void run(); } Runner类如下所示: public class Runner implements IRunner { @Override public void

【设计模式】Proxy 代理模式

[设计模式]Proxy 代理模式 1.代理模式的定义 代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问. 2.静态代理 首先我们通过案例来引出为什么我们需要使用代理模式. 我们给出如下一个接口Moveable 和该接口的实现类: Moveable.java package com.proxy; public interface Moveable { void move(); } Tank.java package com.proxy; import java.util.Rando

&quot;围观&quot;设计模式(12)--结构型之代理模式(Proxy Pattern)

维基百科 代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式. 所谓的代理者是指一个类可以作为其它东西的接口.代理者可以作任何东西的接口:网络连接.内存中的大对象.文件或其它昂贵或无法复制的资源.----WIKIPEDIA 个人理解 代理模式就是找另外的一个对象作为代理去为你实施请求,代理模式分为两种,一种是静态代理模式,另外一种是动态代理模式,静态代理模式是代理类为其创建一个对象,将需要代理的类的对象赋予代理类中的该对象,让代理类中该对象去代替需要代理的类的对象去执行一定的

.net设计模式-代理模式

1.行为型设计模式:关注类与类之间的关系 代理模式:通过代理类来访问业务类,在不修改业务类的前提下可以扩展功能: 业务接口 1 /// <summary> 2 /// 业务接口 3 /// </summary> 4 public interface ISubject 5 { 6 /// <summary> 7 /// get 8 /// </summary> 9 /// <returns></returns> 10 bool GetS

juc下的并发工具类和线程池

工具类 CountDownLatch 利用它可以实现类似计数器的功能.比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了. package com.yjc.juc; import java.util.concurrent.CountDownLatch; public class CountDownLatchDemo { public static void main(String[] args) throws Interrupt

Mybatis深入之数据库连接池原理

Mybatis深入之数据库连接池原理 简介 主要记录Mybatis数据库连接池实现原理.如何使用连接池来管理数据库连接的.连接池如何向外提供数据库连接.当外部调用使用完成之后是如何将数据库连接放回数据库连接池的. 准备 有前面的相关文章的铺垫.这里就不再从Mybatis数据库相关信息的初始化以及何时创建一个真正的数据库连接并且向外提供使用的.这两方面的过程可以参见Mybatis深入之DataSource实例化过程和Mybatis深入之获取数据库连接两篇文章. 了解Mybatis数据库连接池如何配

数据库连接池原理详解与自定义连接池实现

实现原理 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数制约.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中. 连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象.使