java通过代理创建Conncection对象与自定义JDBC连接池
最近学习了一下代理发现,代理其实一个蛮有用的,主要是用在动态的实现接口中的某一个方法而不去继承这个接口所用的一种技巧,首先是自定义的一个连接池
代码如下
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. 释放连接
-------> 连接放回集合中(..)
*
*/
public class TestMyPool {
private int init_count = 3; // 初始化连接数目
private int max_count = 6; // 最大连接数
private int current_count = 0; // 记录当前使用连接数
// 连接池 (存放所有的初始化连接)
private LinkedList<Connection> pool = new LinkedList<Connection>(); //1. 构造函数中,初始化连接放入连接池
public TestMyPool() {
// 初始化连接
for (int i=0; i<init_count; i++){
// 记录当前连接数目
current_count++;
// 创建原始的连接对象
Connection con = createConnection();
// 把连接加入连接池
pool.addLast(con);
}
} //2. 创建一个新的连接的方法
private Connection createConnection(){
try {
Class.forName("com.mysql.jdbc.Driver");
// 原始的目标对象
final Connection con = DriverManager.getConnection("jdbc:mysql:///jdbc_demo", "root", "root"); /**********对con对象代理**************/ // 对con创建其代理对象
Connection proxy = (Connection) Proxy.newProxyInstance( con.getClass().getClassLoader(), // 类加载器
//con.getClass().getInterfaces(), // 当目标对象是一个具体的类的时候
new Class[]{Connection.class}, // 目标对象实现的接口 new InvocationHandler() { // 当调用con对象方法的时候, 自动触发事务处理器
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 方法返回值
Object result = null;
// 当前执行的方法的方法名
String methodName = method.getName(); // 判断当执行了close方法的时候,把连接放入连接池
if ("close".equals(methodName)) {
System.out.println("begin:当前执行close方法开始!");
// 连接放入连接池 (判断..)
pool.addLast(con);
System.out.println("end: 当前连接已经放入连接池了!");
} else {
// 调用目标对象方法
result = method.invoke(con, args);
}
return result;
}
}
);
return proxy;
} catch (Exception e) {
throw new RuntimeException(e);
}
} //3. 获取连接
public Connection getConnection(){ // 3.1 判断连接池中是否有连接, 如果有连接,就直接从连接池取出
if (pool.size() > 0){
return pool.removeFirst();
} // 3.2 连接池中没有连接: 判断,如果没有达到最大连接数,创建;
if (current_count < max_count) {
// 记录当前使用的连接数
current_count++;
// 创建连接
return createConnection();
} // 3.3 如果当前已经达到最大连接数,抛出异常
throw new RuntimeException("当前连接已经达到最大连接数目 !");
} //4. 释放连接
public void realeaseConnection(Connection con) {
// 4.1 判断: 池的数目如果小于初始化连接,就放入池中
if (pool.size() < init_count){
pool.addLast(con);
} else {
try {
// 4.2 关闭
current_count--;
con.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
} public static void main(String[] args) throws SQLException {
TestMyPool pool = new TestMyPool();
System.out.println("当前连接: " + pool.current_count); // 3 // 使用连接
pool.getConnection();
pool.getConnection();
Connection con4 = pool.getConnection();
Connection con3 = pool.getConnection();
Connection con2 = pool.getConnection();
Connection con1 = pool.getConnection(); // 释放连接, 连接放回连接池
// pool.realeaseConnection(con1);
/*
* 希望:当关闭连接的时候,要把连接放入连接池!【当调用Connection接口的close方法时候,希望触发pool.addLast(con);操作】
* 把连接放入连接池
* 解决1:实现Connection接口,重写close方法
* 解决2:动态代理
*/
con1.close(); // 再获取
pool.getConnection(); System.out.println("连接池:" + pool.pool.size()); // 0
System.out.println("当前连接: " + pool.current_count); // 3
} }
在这里使用代理主要是为了监测Connection 中的close()方法,当然也可以检测Connection中的其他方法,顺便值得一提的是还有Jdbc的两个开源连接数据库的框架可以为连接数据库省去一些代码:例如dbcp和c3p0这两个框架实现代码分别如下,但前提必须将对应的jar包导入
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test; public class App_Dbcp { public App_Dbcp() {
// TODO Auto-generated constructor stub
} /**
* 硬编码方式
*/
@Test
public void testDbcp()
{
//DBCP中的核心类
BasicDataSource dataSource = new BasicDataSource();
//连接池配置参数,初始化连接参数,最大连接参数,连接的驱动名 dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
dataSource.setUrl("jdbc:sqlserver://localhost:1433;DatabaseName=教学库");
dataSource.setUsername("sa");
dataSource.setPassword("****"); dataSource.setInitialSize(3);//设置初始化连接参数
dataSource.setMaxActive(6);//设置最大连接数
dataSource.setMaxIdle(3000);//设置最大空闲时间
//获取连接
try {
Connection con = dataSource.getConnection();
con.prepareStatement("delete from tb_user where id=3").executeUpdate();
//关闭
con.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
} } @Test
public void testDBCP()
{
/**
* 使用配置方式来获取参数
*/ try
{
Properties props = new Properties(); InputStream in = App_Dbcp.class.getResourceAsStream("/db.properties");
//读取流文件
props.load(in); //根据Props配置文件直接产生数据对象 DataSource dataSource = BasicDataSourceFactory.createDataSource(props); //创建连接对象
Connection con = dataSource.getConnection();
con.prepareStatement("delete from tb_user where id=4").executeUpdate();
con.close();
}catch(Exception e)
{
throw new RuntimeException(e);
}
}
}
c3p0连接池的测试代码
package gz.itcast.b_c3p0; import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException; import org.junit.Test; import com.mchange.v2.c3p0.ComboPooledDataSource; public class App { public App() {
// TODO Auto-generated constructor stub
} //硬编码方式,使用c3p0连接池来管理连接数目
@Test
public void testCode() throws Exception {
//创建c3p0核心类
ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.microsoft.sqlserver.jdbc.SQLServerDriver");
dataSource.setJdbcUrl("jdbc:sqlserver://localhost:1433;DatabaseName=教学库");
dataSource.setUser("sa");
dataSource.setPassword("***");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(6);
dataSource.setMaxIdleTime(3000); Connection con = dataSource.getConnection(); con.prepareStatement("delete from tb_user where id=3").executeUpdate();
con.close();
} //c3p0使用xml配置文件来管理连接方式 @Test
public void testXml() throws Exception
{
//c3p0核心类,在new 一个对象时就会自动的加载c3p0-config.xml文件
ComboPooledDataSource dataSource = new ComboPooledDataSource(); Connection con = dataSource.getConnection();
con.prepareStatement("delete from tb_user where id=2").executeUpdate(); //关闭连接
con.close();
}
}
对应的xml配置文件
<c3p0-config>
<default-config>
<property name="driverClass">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<property name="url">jdbc:sqlserver://localhost:1433;DatabaseName=教学库</property>
<property name="username">sa</property>
<property name="password">****</property>
<property name="initialPoolSize">3</property>
<property name="maxPoolSize">6</property>
<property name="maxIdleTime">3000</property>
<!--
<user-overrides user="swaldman">
<property name="debugUnreturnedConnectionStackTraces">true</property>
</user-overrides>
--> </default-config> <!--
<named-config name="dumbTestConfig">
<property name="maxStatements">200</property>
<property name="jdbcUrl">jdbc:test</property>
<user-overrides user="poop">
<property name="maxStatements">300</property>
</user-overrides>
</named-config>
--> </c3p0-config>
最后就到为止了
java通过代理创建Conncection对象与自定义JDBC连接池的更多相关文章
- 自定义JDBC链接池
上篇简单介绍了jdbc链接数据库: 本篇就说一下自定义连接池以及增删改查的测试: 自定义连接池 自定义链接池的原因 JDBC连接中用到Connection 在每次对数据进行增删查改 都要 开启 ...
- JDBC连接池-自定义连接池
JDBC连接池 java JDBC连接中用到Connection 在每次对数据进行增删查改 都要 开启 .关闭 ,在实例开发项目中 ,浪费了很大的资源 ,以下是之前连接JDBC的案例 pack ...
- 自定义一个简单的JDBC连接池
一.什么是JDBC连接池? 在传统的JDBC连接中,每次获得一个Connection连接都需要加载通过一些繁杂的代码去获取,例如以下代码: public static Connection getCo ...
- Java之JDBC连接池
数据库连接池 连接池的概述 概念:其实就是一个容器(集合),存放数据库连接的容器. 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时, 从容器中获取连接对象,用户访问完之后 ...
- Java中JDBC连接池&JDBCTemplate
数据库连接池 概念:其实就是一个容器(集合),存放数据库连接的容器. 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归 ...
- c3p0数据库连接池 原创: Java之行 Java之行 5月8日 一、连接池概述 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程
c3p0数据库连接池 原创: Java之行 Java之行 5月8日 一.连接池概述 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程 DB连接池HikariCP为什么如此快 原创: D ...
- Java反射机制(创建Class对象的三种方式)
1:SUN提供的反射机制的类: java.lang.Class<T> java.lang.reflect.Constructor<T> java.lang.reflect.Fi ...
- 透析Java本质-谁创建了对象,this是什么
是构造方法创建的对象吗 package com.java.essence_36; import java.util.ArrayList; import java.util.List; /** * Cr ...
- Java基础之创建实例化对象的方式
Java中创建(实例化)对象的五种方式 1.用new语句直接创建对象,这是最常见的创建对象的方法. 2.通过工厂方法返回对象,如:String str = String.valueOf(23); 3 ...
随机推荐
- 《阿里巴巴Java开发手册1.4.0》阅读总结与心得(三)
(六)工程结构 (一)应用分层 1. [推荐]图中默认上层依赖于下层,箭头关系表示可直接依赖,如:开放接口层可以依赖于Web 层,也可以直接依赖于 Service 层,依此类推: 开放接口层: ...
- docker进阶1-命令补充和容器卷使用
命令补充 docker信息与帮助 docker version 和 docker info docker --help 查看所有docker命令列表 docker --help run/commit/ ...
- Gson的解析Json数据的两种方式
转载:https://blog.csdn.net/huplion/article/details/78984977 在线JSON字符串转Java实体类(JavaBean.Entity): https: ...
- 选择排序、快速排序、归并排序、堆排序、快速排序实现及Sort()函数使用
1.问题来源 在刷题是遇到字符串相关问题中使用 strcmp()函数. 在函数比较过程中有使用 排序函数 Sort(beg,end,comp),其中comp这一项理解不是很彻底. #include & ...
- CodeForces 1082 G Petya and Graph 最大权闭合子图。
题目传送门 题意:现在有一个图,选择一条边,会把边的2个顶点也选起来,最后会的到一个边的集合 和一个点的集合 , 求边的集合 - 点的集合最大是多少. 题解:裸的最大权闭合子图. 代码: #inclu ...
- CF - 652F Ants on a Circle
题目传送门 题解: 先观察蚂蚁相撞, 可以发现, 如果我们将相撞的2个蚂蚁互换位置的话,蚂蚁相当于没有碰撞体积,直接穿过去了.所以我们可以直接计算出最终哪些位置上会有蚂蚁. 接下来就需要知道蚂蚁们的最 ...
- 51nod 1086 背包问题 V2(二进制优化多重背包)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1086 题解:怎么用二进制优化多重背包,举一个例子就明白了. ...
- 数论 线性同余方程的应用 poj2891
Strange Way to Express Integers Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 17321 ...
- map + filter + reduce
map 是对 集合 里面的元素一个接一个的进行某种运算,常常与lambda 结合使用 #求平方: items = [1, 2, 3, 4, 5] squared = list(map(lambda ...
- JavaScript漫谈之理解类型操作符typeof
在本文中,将简述JavaScript类型系统和数据类型,以及如何使用typeof操作符执行类型检查. 还讲解了使用typeof操作符进行某些数据类型检查是不完善的,并介绍其他几种类型检查的方法. 更多 ...