一、自定义数据库连接池实现思想
依赖的jar
1、思想步骤
- 1、链接池类
- 2、制定全局参数,初始化数目,最大连接数,当前连接,链接池集合
- 3、构造函数循环创建3个链接
- 4、写一个从创建连接的方法
- 5、获取连接
判断有链接直接拿
是否达到最大连接数,达到抛出异常
没达到创建新连接 - 6、释放链接 放回集合中
- 7、优化连接 扩展close()方法 动态代理
2、思想原理图
3、优化:
当关闭连接时候把链接放入连接池 就是调用clos()方法触发releaseConnection(Connection conn)方法
*解决1:继承Connection重写clos方法 方法太多不可行
*解决2:动态代理
如果对某个接口中得到某个方法进行扩展,而不想实现接口所有的方法可以使用的动态代理模式
java中代理模块:静态,动态,cglib代理
动态代理可以及检测接口中方法的执行
如何生成动态代理 jdk API提供Proxy
static Object newProxyInstance{
ClassLoader loader //当前使用的类加载器
Class<?>interface //目标对象Connection实现的接口类型
InvocationHabdler h //事件处理器,当执行上面接口中的方法的时候, 就自动触发处理器方法,把当前执行的发方法(method)作为参数传入
}
二、代码实现
1、定义获取连接的接口DataSource.java
package work.doudou.MyPool;
import java.sql.Connection;
//定义获取连接的接口
public interface DataSource {
public Connection getConnection();
}
2、数据源BasicDataSource.java
package work.doudou.MyPool;
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.util.LinkedList;
/**
* 自定义链接池
* 1、MyPool.java类,链接池类
* 2、制定全局参数,初始化数目,最大连接数,当前连接,链接池集合
* 3、构造函数循环创建3个链接
* 4、写一个从创建连接的方法
* 5、获取连接
* 判断有链接直接拿
* 是否达到最大连接数,达到抛出异常
* 没达到创建新连接
* 6、释放链接 放回集合中
* 7、优化连接 扩展close()方法 动态代理
**/
/* 优化:
* 当关闭连接时候把链接放入连接池 就是调用clos()方法触发releaseConnection(Connection conn)方法
* 解决1:继承Connection重写clos方法 方法太多不可行
* 解决2:动态代理
* 如果对某个接口中得到某个方法进行扩展,而不想实现接口所有的方法可以使用的动态代理模式
* java中代理模块:静态,动态,cglib代理
* 动态代理可以及检测接口中方法的执行
* 如何生成动态代理 jdk API提供Proxy
* static Object newProxyInstance{
* ClassLoader loader 当前使用的类加载器
* Class<?>interface 目标对象Connection实现的接口类型
* InvocationHabdler h 事件处理器,当执行上面接口中的方法的时候,就自动触发
* 处理器方法,把当前执行的发方法(method)作为参数传入
* }
*/
public class BasicDataSource implements DataSource{
//数据库连接账号
private String username=null;
//数据库连接密码
private String password=null;
//驱动com.mysql.jdbc.Driver
private String driver=null;
//数据库连接url jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8","root","root
private String url=null;
//初始化数目
private int init_count=3;
//最大连接数
private int max_count=5;
//连接池里头的连接
private int current_count=0;
//连接池,存放链接
private LinkedList<Connection> connections=new LinkedList<Connection>();
//1、初始化连接放入连接池
private void createBasicDataSource(){
//初始化连接
for(int i=0;i<init_count;i++){
//记录当前连接数
current_count++;
//把链接放入连接池
connections.addLast(createConnection());
}
}
//2、建新连接的方法
private Connection createConnection(){
try {
Class.forName(driver);
//原始的目标对象
final Connection conn= DriverManager.getConnection(url,username,password);
/*******创建代理对象********/
//创建代理对象
Connection proxyConnection=(Connection)Proxy.newProxyInstance(
//类加载器
conn.getClass().getClassLoader(),
//目标接口对象
new Class[] {Connection.class},
//当调用conn对象的时候自动触发事务处理器
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法返回值
Object result=null;
//当前执行的方法名
String methoName=method.getName();
//判断执行close()就把连接放入连接池
if ("close".equals(methoName)) {
//连接放入连接池
if(connections.size()<init_count){
connections.addLast(conn);
}else{
//如果连接池满了就关了连接
try {
current_count--;
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}else{
//调用目标方法对象
result=method.invoke(conn, args);
}
return result;
}
});
return proxyConnection;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
//3、获取连接
@Override
public Connection getConnection() {
//获取连接之前判断是否初始化
if (connections.size()<=0) {
createBasicDataSource();
}
//判断是否连接,有就去出,,就直拿
if (connections.size()>0) {
return connections.removeFirst();
}
//判断连接池有没有连接,如果没有达到最大连接,就创建
if (current_count<max_count) {
//记录当前连接使用数
current_count++;
//创建连接
return createConnection();
}
//如果已达到最大连接数就,就抛出异常
throw new RuntimeException("当前连接已达到最大连接数目!");
}
//4、释放链接
public void releaseConnection(Connection conn) {
//判断当前连接池数目如果少于初始化就放入池中
if(connections.size()<init_count){
connections.addLast(conn);
}else{
//如果连接池满了就关了连接
try {
current_count--;
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getInit_count() {
return init_count;
}
public void setInit_count(int init_count) {
this.init_count = init_count;
}
public int getMax_count() {
return max_count;
}
public void setMax_count(int max_count) {
this.max_count = max_count;
}
public int getCurrent_count() {
return current_count;
}
public LinkedList<Connection> getConnections() {
return connections;
}
}
3、测试类test.java
package work.doudou.MyPool;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class test {
//创建数据库连接池基础数据源的对象
static BasicDataSource pool=new BasicDataSource();
//设置基础数据
static{
pool.setUsername("root");
pool.setPassword("root");
pool.setDriver("com.mysql.jdbc.Driver");
pool.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8");
pool.setInit_count(5);
pool.setMax_count(7);
}
//返回连接池对象
public static DataSource getDataSource() {
return pool;
}
//测试主方法
public static void main(String[] args) {
//获取数据库连接
Connection connection=getDataSource().getConnection();
//查询执行器
Statement s=null;
//返回结果集
ResultSet rs=null;
//控制台输出获取到连接的地址
System.out.println(connection);
try {
//执行查询
s=connection.createStatement();
rs=s.executeQuery("select * from a");
while (rs.next()) {
System.out.println(rs.getInt("a"));
}
//关闭结果集
rs.close();
//关闭执行器
s.close();
//这里关闭连接是吧连接放回连接池
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("总共的连接数目"+pool.getCurrent_count());
System.out.println("连接池里空闲的连接"+pool.getConnections().size());
}
}