为什么要有数据库连接池

1.创建Connection的过程是很耗时的
2.一个Connection只能供一个对象使用(所以不能使用单例模式)
3.所以要先创建一堆连接,要一个给你一个,用完了还回来。

什么是代理模式


龙哥总结:

从静态代理的使用上来看,我们一般是这么做的。

           1,代理类一般要持有一个被代理的对象的引用。

2,对于我们不关心的方法,全部委托给被代理的对象处理。

3,自己处理我们关心的方法。


代理模式

在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。

介绍

意图:为其他对象提供一种代理以控制对这个对象的访问。

主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

何时使用:想在访问一个类时做一些控制。

如何解决:增加中间层。

关键代码:实现与被代理类组合。

应用实例:

优点:

缺点:

使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。

注意事项:

实现

我们将创建一个 Image 接口和实现了 Image 接口的实体类。ProxyImage 是一个代理类,减少 RealImage

ProxyPatternDemo,我们的演示类使用 ProxyImage 来获取要加载的 Image



代理模式实例-数据库连接池的实现_sql


数据库连接

原本获得数据库连接需要干的事情

代理模式实例-数据库连接池的实现_代理模式_02

数据库连接池

代理模式实例-数据库连接池的实现_代理模式_03

代码实现

1.创建类ConnectionProxy实现java.sql.Connection接口

2.类ConnectionProxy分别实现基础构造方法,close方法

以及要使用的prepareStatement及createStatement

代理模式实例-数据库连接池的实现_代理模式_04


3.实现DataSource,因为数据库连接池只有一个(所以使用单例模式)

4.DataSource具有的特点其他博客写的很清楚了

ConnectionProxy代码

import java.sql.*;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

public class ConnectionProxy implements Connection
//设置连接
private Connection connection;
//使用createStatement的方法,如果返回为空,则在后续使用会空指针异常
@Override
public Statement createStatement() throws SQLException {
return this.connection.createStatement();
}
//构造函数,返回连接
public ConnectionProxy() throws SQLException {
this.connection = DataSource.getInstance().getConnection();

}
//同createSatement
@Override

public PreparedStatement prepareStatement(String sql) throws SQLException {
return this.connection.prepareStatement(sql);
}
//重要的close方法
@Override
public void close() throws

数据库连接池DataSource

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;

public class DataSource

private static String url="jdbc:mysql://127.0.0.1:3306/usertest?useUnicode=true&characterEncoding=utf8";
private static String user="root";
private static String password="xxx";
private static int maxConnection=500;
private static int currentConnection=0;

//LinkedList是非线程安全的所以在操纵LinkedList的时候需要加锁

//需要序列化和反序列化实现单例
private static LinkedList<Connection> connectionList=new LinkedList<Connection>();
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private static Connection createNewConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
private DataSource(){
//类初始化不需要加锁
if (connectionList==null||connectionList.size()==0){
for (int i = 0; i < 10; i++) {
try {
connectionList.add(createNewConnection());
} catch (SQLException e) {
e.printStackTrace();
}
currentConnection++;
System.out.println("当前共有连接"+currentConnection);
}
}
}

public Connection getConnection() throws SQLException {

synchronized (DataSource.class){
if (connectionList.size()>0){
System.out.println("有连接可以,从LinkedList中移除一个连接");
return connectionList.remove();
}

if (currentConnection<maxConnection){
try {
return createNewConnection();
} catch (SQLException e) {
e.printStackTrace();
}

}
}
throw new SQLException("无连接可用");
}

public void recoveryConnection(Connection connection){
System.out.println("DataSource获得恢复连接");
synchronized (DataSource.class) {
connectionList.add(connection);
}
}

public static DataSource getInstance(){
return DataSourceInstance.dataSource;
}

private static class DataSourceInstance{
//这里需要写成单例模式 这里使用内部静态类实现单例模式
private static DataSource dataSource = new

写在最后

数据库连接池的实现使用静态代理即可,推荐大家搭配我前面的博客数据库的操作封装使用,相当于自己写了框架Mybatis的感觉,特别爽。