代理模式之连接池的设计

一、数据源的设计-->MyDataSource

     

class MyDataSource{
    private static String url = "jdbc:mysql:///daxia";
    private static String user = "root";
    private static String password = "root";
	//初始化连接数
	private static int initCount = 3;
	//最大连接数
	private static int maxCount = 5;
	//当前连接数
	int currentCount = 0;
	//对于操作对象的性能较ArrayList好
	LinkedList<Connection> connectionsPool = new LinkedList<Connection>();
	public MyDataSource() {
		try {
			for (int i = 0; i < initCount; i++) {
			//把初始化的连接对象存放到链表里面
			this.connectionsPool.addLast(this.createConnection());
			this.currentCount++;
			}
		} catch (SQLException e) {
			throw new ExceptionInInitializerError(e);
		}
	}

	public Connection getConnection() throws SQLException {
		synchronized (connectionsPool) {
			if (this.connectionsPool.size() > 0)
			//从链表里面删除头一个连接对象,并返回该连接对象
			return this.connectionsPool.removeFirst();
			if (this.currentCount < maxCount) {
				this.currentCount++;
				return this.createConnection();
			}
			throw new SQLException("已没有链接");
		}
	}

	public void free(Connection conn) {
		//释放连接,把当前连接加到链表尾,并没有真正关闭
		this.connectionsPool.addLast(conn);
	}

	//父类引用指向子类对象
	private Connection createConnection() throws SQLException {
		 Connection realConn = DriverManager.getConnection(url, user, password);
		 return new MyConnection(realConn, this);
	}

}

 

 

二、代理连接类设计-->MyConnection

 

public class MyConnection implements Connection {
                 //真正的连接对象
	private Connection realConnection;  //组合
           //数据源
	private MyDataSource  dataSource;
                 //连接使用的最大次数,超过这个次数,将真正关闭这个连接
	private int maxUseCount = 5;
	private int currentUserCount = 0;
	MyConnection(Connection connection, MyDataSource dataSource) {
		this.realConnection = connection;
		this.dataSource = dataSource;
	}
	public void clearWarnings() throws SQLException {
		this.realConnection.clearWarnings();
	}
                 //我们关心的方法
	public void close() throws SQLException {
		this.currentUserCount++;
		if (this.currentUserCount < this.maxUseCount)
		//把代理Connection放进去,不要把真正的连接放回,这样这个方法才有效	
                                  this.dataSource.connectionsPool.addLast(this);
		else {
			this.realConnection.close();
			this.dataSource.currentCount--;
		}
	}

	public void commit() throws SQLException {
		this.realConnection.commit();   
	}

	public Statement createStatement() throws SQLException {
		return this.realConnection.createStatement();
	}
        //其他方法略.........
}

  

 

三、jdbc工具类设计-->JdbcUtils

public final class JdbcUtils {
	private static MyDataSource myDataSource = null;
	private JdbcUtils() {
	}
	static {
		try {
			Class.forName("com.mysql.jdbc.Driver");// 只执行一次
                                 //加载了驱动后才能实例化
			myDataSource = new MyDataSource();
		} catch (ClassNotFoundException e) {
			throw new ExceptionInInitializerError(e);
		}
	}

	public static Connection getConnection() throws SQLException {
		return myDataSource.getConnection();
	}

	public static void free(Connection conn) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
		}
	}
}

 

四、 客户端测试类-->TestConnection

public class TestConnection{
	public static void main(String[] args) {
		
		try {
			for(int i=0;i<20;i++){
			Connection conn = JdbcUtils.getConnection();
			System.out.println(conn);
			JdbcUtils.free(conn);
			}
		} catch (SQLException e) {
		e.printStackTrace();			   	   
		}

	}
}

 五、总结

     MyDataSource类实例化后,会创建多个连接对象,并把这个对象存放到连接池(connectionsPool)里面去,方便以后的调用。由于创建连接对象比创建一般的对象的成本要高很多。所以MyDataSource类在程序中只实例化一次,即单例.

 

     MyConnection 实现了java.sql.Connection类,Connection能做的MyConnection都能做.但我们关心的只有Connection接口的close方法.其他方法的实现真正的连接类realConnection去做.

 

MyDataSource与MyConnection 相对于客户端是透明的,客户端使用Connection接口引用MyConnection 对象!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值