动态代理&模拟一个数据库连接池

数据库连接池:说白了就是在一个池子中(容器)中放了很多的数据库连接,当用户需要的时候就从中取出来一个用,用完了就放回连接池中。

优点:极大的提高了数据库的效率。

对于自定义的数据库连接池我们使用一个LinkedList做数据库连接池.这个集合的特点是增删快,查询慢。

自定义一个数据库连接池的步骤:

1.自定义一个类实现DataSource接口。

2.定义一个List<Connection> list=new LinkedList<Connection>();存放数据库连接。

3.初始化数据库连接池。就是在静态代码块static块中添加数据库的连接若干到list中(连接池)。

4.写一个方法returnPool(Connection con)还回到数据库连接池。如果数据库连接池中没有数据连接可用,就添加若干个带数据库连接池list中。

5.在getConnection()方法中动态代理重新改造Connection的close方法,因为我们不能够用完了就关闭,而是应该用完了还回数据库连接池中。这样可以循环使用。

案例:

自定义自己的数据库连接池MyPool

package com.itheima.mypools;

import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;

import javax.sql.DataSource;

public class MyPool implements DataSource{
	//1.需要一个容器存放连接
	private static List<Connection> list=new LinkedList<Connection>();
	//初始化加载类的时候就在连接池中添加了5个连接
	static{
		try {
			//2.加载驱动
			Class.forName("com.mysql.jdbc.Driver");
			for(int i=0;i<5;i++){
				//3.获取连接
				Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "169500");
				list.add(con);
			}
		}catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
	@Override
	public Connection getConnection() throws SQLException {
		//如果连接池的数据没有了就添加3个连接到连接池中
		if(list.size()==0){
			for(int i=0;i<3;i++){
				Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "169500");
				list.add(con);
			}
		}
		//获取连接,就是把连接池中的连接remove不是get...
		final Connection con = list.remove(0);
		
		//需要重写连接的close()方法,我们使用动态代理
		Connection proxy=(Connection) Proxy.newProxyInstance(con.getClass().getClassLoader(), con.getClass().getInterfaces(), new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)//proxy代理类对象 method被代理类的方法,args被代理类方法的参数
					throws Throwable {
				if("close".equals(method.getName())){
					//要改造的方法就还回连接池
					returnPool(con);
					return null;
				}else{
					//不想改造的方法就使用被代理者对象的方法
					return method.invoke(con, args);
				}
			}
		});
		System.out.println("获取了一个连接,连接池中还有:"+list.size()+"个连接");
		return proxy;
	}
	public void returnPool(Connection con){
		try {
			if(con!=null&&!con.isClosed()){
				list.add(con);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		System.out.println("还回了一个连接,池里还剩余"+list.size()+"个连接");
	}
	@Override
	public PrintWriter getLogWriter() throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public int getLoginTimeout() throws SQLException {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public Connection getConnection(String username, String password)
			throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}
	
}
使用这个自己定义的数据库连接池:

package com.itheima.mypools;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import cn.itheima.utils.JDBCUtils;

public class JDBCDemo1 {
	public static void main(String[] args) {
		Connection con=null;
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			//使用数据库连接池
			MyPool pool=new MyPool();
			//获取连接
			con=pool.getConnection();
			ps=con.prepareStatement("select * from account");
			rs=ps.executeQuery();
			while(rs.next()){
				String name=rs.getString("name");
				System.out.println(name);
			}
		} catch (SQLException e) {
			e.printStackTrace();
			throw new RuntimeException();
		}finally{
			//这里的close已经被更该过了
			if(rs!=null){
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}finally{
					rs=null;
				}
			}
			if(ps!=null){
				try {
					ps.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}finally{
					ps=null;
				}
			}
			if(con!=null){
				try {
					con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}finally{
					con=null;
				}
			}
		}
		
	}
}
运行结果:






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值