概述
分析
实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程,为了解决此类性能问题,通常情况我们采用连接池技术,来共享连接Connection
概念
用池来管理Connection,这样可以重复使用Connection。有了池,所以我们就不用自己来创建 Connection’而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close() 方法也不会真的关闭Connection,而是把Connection “归还”给池。池就可以再利用这个Connection 对象了。
规范
Java为数据库连接池提供了公共的接口:javax.sqI.DataSource,各个厂商需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!
常见的连接池:DBCP、C3POO
自定义连接池
分析
根据我们对连接池简单的理解,如果我们要编写自定义连接池,需要完成以下步骤
- 创建连接池实现(数据源),并实现接口 javax.sqI.DataSource 。因为我们只使用该接口中getConnection()方法,简化本案例,我们将自己提供方法,而没有实现接口
- 提供一个集合,用于存放连接,因为移除/添加操作过多,所以选择LinkedList
- 本案例在静态代码块中,为连接池初始化3个连接
- 之后程序如果需要连接,调用实现类的getConnection(),本方法将从连接池(容器List)获得连接。为了保证当前连接只能提供给一个线程使用,所以我们需要将连接先从连接池中移除
- 当用户使用完连接,释放资源时,不执行close()方法,而是将连接添加到连接池中
准备
- 写好配置文件后,通过静态代码块加载配置文件信息
1 | public class JDBCUtils_V3 { |
实现
1 | public class MyDataSource implements DataSource{ |
自定义连接池:方法增强
自定义连接池中存在严重问题,用户调用getConnection()获得连接后,必须使用release()方法进行连接的归还,如果用户调用conn.close()将连接真正的释放,连接池中将出现无连接可用。
此时我们希望,即使用户调用了close()方法,连接仍归还给连接池。close()方法原有功能时释放资源,期望功能:将当前连接归还连接池。说明se()方法没有我们希望的功能,我们将对close() 方法进行增强,从而实现将连接归还给连接池的功能
方法增强总结
- 继承:子类继承父类,将父类的方法进行复写,从而进行增强。
- 使用前提:必须有父类,且存在继承关系
- 装饰者设计模式:此设计模式专门用于增强方法。
- 使用前提:必须有接口
- 缺点:需要将接口的所有方法都实现
- 动态代理:在运行时动态的创建代理类,完成增强操作。
- 与装饰者相似使用前提:必须有接口
- 难点:需要反射技术
- 字节码增强:运行时创建目标类子类,从而进行增强常见
- 第三方框架:cglib、javassist等
装饰者设计模式
设计模式:专门为解决某一类问题,而编写的固定格式的代码。
装饰者固定结构:接口A,己知实现类c,需要装饰者创建代理类B
- 创建类B,并实现接口A
- 提供类B的构造方法,参数类型为A,用于接收A接口的其他实现类(c)
- 给类B添加类型为A成员变量,用于存放A接口的其他实现类
- 增强需要的方法
- 实现不需要增强的方法,方法体重调用成员变量存放的其他实现类对应的方法
实现
1 | //1.实现同一个接口Connection |
使用装饰类
C3P0连接池
导入Jar包
mchange-commons-java-0.2.3.4.jar
配置文件
- 配置文件名称:c3p0-config.xml (固定)
- 配置文件位置:src(类路径)
- 配置文件内容:命名配置
常见配置项
编写工具类
- 未抽取工具类之前
1 | public class TestC3P0 { |
- 抽取工具类
1 | public class C3P0Utils { |
- 抽取工具类后的测试类可以这样写
1 | public class TestC3P0 { |