由c3p0或者druid创建出来的连接池,获取连接和操做对象后,调用close方法,不是真正的关闭
这是我的配置文件,初始化连接数是3,最大连接数是5
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/demobase?useSSL=false&serverTimezone=GMT
username=root
password=dong
#//属性类型的字符串,通过别名的方式配置扩展插件, 监控统计用的stat 日志用log4j 防御sql注入:wall
filters=stat
initialSize=3
maxActive=5
maxWait=60000
这是Druid连接池工具 主要用来演示获取连接,具体内容不写太多
public class DruidUtil {
static DataSource dataSource;
static Properties properties = new Properties();
static {
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("durid.properties");
try {
properties.load(is);
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
}catch (Exception e){
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
public static void close(Connection conn, Statement ps, ResultSet rs){
.......
}
}
开始实验
public class Test2 {
public static void main(String[] args) throws SQLException {
Connection connection1 = DruidUtil.getConnection();
System.out.println("1: "+connection1);
Connection connection2 = DruidUtil.getConnection();
System.out.println("2: "+connection2);
Connection connection3 = DruidUtil.getConnection();
System.out.println("3: "+connection3);
Connection connection4 = DruidUtil.getConnection();
System.out.println("4: "+connection4);
Connection connection5 = DruidUtil.getConnection();
System.out.println("5: "+connection5);
Connection connection6 = DruidUtil.getConnection();
System.out.println("6: "+connection6);
}
}
由于最大连接数是5,所以第6个连接一直处于等待状态,最终打印结果如下:
在connection3,connection后加上
cconnection3.close();
cconnection4.close();
打印结果变为:
可以看到connection 3,4,5的地址是一样的,原因是:
connection3关闭后,被回收,connection4获取连接,获取的是上一次被回收的,connection4关闭后,connection5又获取了这个连接
这就是连接池的回收机制
模仿连接池的原理
1-先找到一个实现了Connection接口的类,我选用的是ConnectionImpl类
2-创建一个代理类
public class ConnProxy extends ConnectionImpl {
private static Connection connection;
public ConnProxy(Connection connection){
this.connection = connection;
}
//这里重写了close方法。
//用该类创建的connection对象,调用的close方法就是我们重写的close方法
//其他的connection操做,都交给ConnectionImpl来实现
@Override
public void close() throws SQLException {
if (DruidUtil.totalCount>3){
DruidUtil.totalCount--;
try {
this.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}else {
DruidUtil.connList.add(this);
}
}
}
3-修改Druid工具类
public class DruidUtil {
private static DataSource dataSource;
private static Properties properties = new Properties();
public static List<Connection> connList = new ArrayList<>();
//记录初始化连接数
static int totalCount = 3;
//设置最大连接数
static int maxCount = 5;
static {
try {
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("durid.properties");
properties.load(is);
dataSource = DruidDataSourceFactory.createDataSource(properties);
Connection conn1 = dataSource.getConnection();
Connection conn2= dataSource.getConnection();
Connection conn3 = dataSource.getConnection();
//用代理类创建Connection对象
Connection connProxy1 = new ConnProxy(conn1);
Connection connProxy2 = new ConnProxy(conn2);
Connection connProxy3 = new ConnProxy(conn3);
connList.add(connProxy1);
connList.add(connProxy2);
connList.add(connProxy3);
}catch (Exception e){
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
if (connList.size()>0){
return connList.remove(0);
}else if (totalCount<maxCount){
totalCount++;
return dataSource.getConnection();
}
return null;
}
public static DataSource getDataSource(){
return dataSource;
}
4-测试
public class DruidAndProxy {
public static void main(String[] args) throws SQLException {
Connection conn1 = DruidUtil.getConnection();
System.out.println(conn1);
Connection conn2 = DruidUtil.getConnection();
System.out.println(conn2);
Connection conn3 = DruidUtil.getConnection();
System.out.println(conn3);
conn3.close();
Connection conn4 = DruidUtil.getConnection();
System.out.println(conn4);
conn2.close();
Connection conn5 = DruidUtil.getConnection();
System.out.println(conn5);
Connection conn6 = DruidUtil.getConnection();
System.out.println(conn6);
}
}
connection 结果:
connection4 用的是 connection3 用过的 connection
connection5 用的是 connection2 用过的 connection
connection6 用的是 临时创建的connection对象
注释掉connection3和2的close方法后,结果如下: