连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要的它们的线程使用,这种把连接“汇集”起来的技术基于这样的一个事实:对于大多数应用程序,当它们正在处理通常需要数毫秒完成的事务时,仅需要能够访问JDBC连接的1个线程 。当不处理事务时,这个连接就会闲置。相反,连接池允许闲置的连接被其它需要的线程使用。
2.使用连接池的好处
a.减少连接创建的时间.获取数据库Connection对象相对来说是花销系统资源.
b.简化了编程模式,每一个单独的线程都能够'像'创建一个自己的JDBC Connection对象,这时用户就能直接使用JDBC编程技术.
c.受控的资源使用,如果不使用连接池技术,而是直接创建获取新的连接,这时程序的资源就会产生非常大的浪费并且可能会导致高负载下的异常发生.
3.数据库连接池技术的原理
其实看上去连接池的技术是挺简单的,传统上每一次访问数据库时,就会打开数据库,获取数据库连接,操作数据然后关闭数据库的连接.这是非常耗费资源滴.
数据库连接池:在项目启动时,会创建一定数量的数据库连接对象存储在一个池中(内存中,Java语言就是集合里),需要使用到数据库连接时,就去池中取连接,而操作完数据库,就将连接放回池中。这样的话,通过复用这些数据库连接,减少对数据库连接直接创建.极大地节省系统资源和时间.
1.连接池的使用步骤可以简单化为这些步骤:
public interface DataSource extends ,
该工厂用于提供到此 DataSource
对象所表示的物理数据源的连接。作为 DriverManager
工具的替代项,DataSource
对象是获取连接的首选方法。实现 DataSource
接口的对象通常在基于 JavaTM Naming and Directory Interface (JNDI) API 的命名服务中注册。
DataSource
接口由驱动程序供应商实现。共有三种类型的实现:
Connection
对象 连接池实现 - 生成自动参与连接池的 Connection
对象。此实现与中间层连接池管理器一起使用。 分布式事务实现 - 生成一个 Connection
对象,该对象可用于分布式事务,大多数情况下总是参与连接池。此实现与中间层事务管理器一起使用,大多数情况下总是与连接池管理器一起使用。
DataSource
对象的属性在必要时可以修改。例如,如果将数据源移动到另一个服务器,则可更改与服务器相关的属性。其优点在于,由于可以更改数据源的属性,所以任何访问该数据源的代码都无需更改。
通过 DataSource
对象访问的驱动程序本身不会向 DriverManager
注册。通过查找操作获取 DataSource
对象,然后使用该对象创建 Connection
对象。使用基本的实现,通过 DataSource
对象获取的连接与通过 DriverManager
设施获取的连接相同。
1.DataSource可以获取对数据库的连接(Connection对象),和DriverManager获取连接的方式是相同的
2.DataSource是SUN公司定义出来的接口,需要不同厂商实现该接口,而实现有三种方式(常用的是连接池的技术实现).这就是连接池和数据源的关系啦.
3.面向接口的编程,使我们将具体的数据库抽离出来.让编程变得简单.
2.连接池实现的话,内部必须要在程序启动时创建一定数量的数据库连接,然后存放在集合中(内存).
private static List<Connection> dataSource = new ArrayList<Connection>();
@Test
* 这时就需要在Connection实现类添加/修改行为.---将连接放回连接池
* 而此时,Connection的实现为:com.mysql.jdbc.Connection存在 Mysql厂商提供的驱动包中.
* 所以,就不能直接修改驱动包中的源代码.----可以直接查看该实现类开源码---没有将连接放回连接池的方法.
* 这时解决方法:
* 1.继承:由于Mysql的中实现类不是final,需要继承该实现类.添加方法.
* class MyConnection extends com.mysql.jdbc.Connection
* 劣势:如果更改数据库时,就要将继承的实现类更改啦.就要依赖具体实现的不同厂商类.所以不推荐使用
* 2.包装设计模式:
* 典型例子:读取文件,并且将行数读出(BufferedReader例子).
* 一般步骤:a.编写一个类,实现被包装类相同的接口.这次被包装的类是com.mysql.jdbc.Connection.
* 所以:class MyConnection1 implements javax.sql.Connection.
* SUN公司规范接口,重写父类的所有的未实现的方法 .
* b.在新编写的类中,定义一个成员变量.为原有(被包装)类的引用.
* private Connection conn;
* c.定义构造方法,把原有类的实例注入进来
* public MyDataSource1(Connection conn){
* this.conn = conn;
* }
* d.对要修改的方法,编写自己的代码
* @Override
* public void close() throws SQLException {
* dataSource.add(conn); //不是关闭连接,而是放回连接池
* }
* e.对于不需要改变的方法,调用原有类的对应方法
* @Override
* public <T> T unwrap(Class<T> iface) throws SQLException {
* return conn.unwrap(iface);
* }
* 3.包装模式加强版(适配器):
* 3.1 适配器类的编写:
* a、编写一个类,实现与被包装类相同的接口(包装类和原有类有着相同的行为)
* public class MyConnectionWrapper implements javax.sql.Connection
* b、定义一个变量,引用原有类的实例
* private Connection conn;
* c、定义构造方法,把原有类的实例注入进来
* public MyConnectionWrapper(Connection conn){
* this.conn = conn;
* }
* d、全部调用原有类的对应方法
* conn.unwrap(iface);.....等等
* 3.2 适配器类的使用:
* a、编写一个类,继承已经实现了接口的包装类
* public class MyConnection2 extends MyConnectionWrapper
* b、定义一个变量,引用原有类的实例
* private Connection conn;
* c、定义构造方法,把原有类的实例注入进来
* public MyConnection2(Connection conn,List<Connection> dataSource){
super( conn);
this.conn = conn;
this.dataSource = dataSource;
}
* d、对于要改变的方法,编写自己的代码
*
@Override
public void close() throws SQLException {
dataSource.add( conn);
}
*
* 4.动态代理模式:从实际看来,包装模式和静态代理十分的相似.
* JDK动态代理:代理类和被代理类都要实现相同的接口
* CGLIB实现动态代理:基于子类的动态代理.
public
class
DynamicProxy
implements
InvocationHandler {
private
Object target;
public
DynamicProxy(Object target) {
this
.target = target;
}
@Override
public
Object invoke(Object proxy, Method method, Object[] args)
throws
Throwable {
before();
Object result = method.invoke(target, args);
after();
return
result;
}
@SuppressWarnings
(
"unchecked"
)
public
<T> T getProxy() {
return
(T) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
}
}
DynamicProxy 实现了 InvocationHandler 接口,那么必须实现该接口的 invoke 方法,参数不做解释,望文生义吧.在该方法中,直接通过反射去 invoke method,在调用前后分别处理 before 与 after
最后将 result 返回.
|
1.DBCP数据源(Apache组织Tomcat专用) 具体的配置请看:http://commons.apache.org/proper/commons-dbcp/index.html 封装DBCPUtil工具类:导入相关的开发架即可 2.C3P0数据源(牛人个人开发) 具体的配置请看:架包中帮助文档 封装C3P0Util工具类:导入相关的开发架即可 3.Druid数据源(阿里巴巴开源) GitHub:https://github.com/alibaba/druid 使用教程:http://blog.csdn.net/yunnysunny/article/details/8657095 数据源,就是内存集合存在一定的数量Connection对象.以后开发使用DataSource获取连接. |
JNDI:JavaTM Naming and Directory Interface 他是一个集合:Map<String,Object>.String:path+name;Object:任意对象。类似window系统的注册表。 一般服务器都是通过JNDI存放数据源的。数据源的配置
1.配置Tomcat管理的数据源
a:把数据库驱动拷贝Tomcat\lib目录中
b:
在应用的
META-INF
目录下,建立一个名称为
context.xml
的配置文件,内容如下:
c:
部署应用,启动
Tomcat
,服务器就会按照配置在
JNDI
容器中注册数据源的实例.
d:获取数据源,
部署应用,启动
Tomcat
,服务器就会按照配置在
JNDI
容器中注册数据源的实例
|