【Java EE 学习 15】【自定义数据库连接池之动态代理的使用】
一、动态代理的作用
使用动态代理可以拦截一个对象某个方法的执行,并执行自定义的方法,其本质是反射
优点:灵活
缺点:由于其本质是反射,所以执行速度相对要慢一些
二、数据库连接池设计思想
1.为什么要使用数据库连接池:创建Connection对象的过程是非常耗时的,为了保证Connection可以重用,应该对Connection进行管理。
2.设计要求:
(1)连接池能够实现维护多个连接,必须要保证每一个线程获取到的是不同的Connection对象。
(2)提供一个方法能够回收连接。
3.最基本的实现
package day15_2; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList; /**
* 使用最基本的方式创建数据库连接池
* @author kdyzm
*
*/
public class JDBCPool1 {
private static ArrayList<Connection>pool=new ArrayList<Connection>();
static
{
try {
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysq://localhost:3306?useUnicode=true&characterEncoding=utf-8";
for(int i=0;i<5;i++)
{
Connection conn=DriverManager.getConnection(url, "root", "5a6f38");
pool.add(conn);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
} public Connection getConn()
{
synchronized (pool) {
Connection conn=pool.remove(0);
System.out.println("还有 "+pool.size()+"个连接");
return conn;
}
} public static void back(Connection conn)
{
System.out.println("还连接:"+conn);
pool.add(conn);
}
}
4.程序员写代码总是习惯性的调用close方法,如果实际调用了close方法,则该连接将会被释放,再也回收不回来了,所以应当使用一种方法拦截close方法的执行,并且替换成自定义的动作。使用代理可以完成这个任务。
代码示例:
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.LinkedList;
import java.util.Properties;
public class ConnUtils {
private static LinkedList<Connection> pool = new LinkedList<Connection>();
static{
try {
//声明资源器类 -
Properties prop = new Properties();
//获取这个文件的路径
URL url = ConnUtils.class.getClassLoader().getResource("jdbc.properties");
String path = url.getPath();
//为了防止有中文或是空格
path = URLDecoder.decode(path,"UTf-8");
File file = new File(path);
//加载jdbc.properties这个文件
prop.load(new FileInputStream(file));
//获取信息
String driver = prop.getProperty("driver");
Class.forName(driver);
String jdbcurl = prop.getProperty("url");
String nm = prop.getProperty("name");
String pwd = prop.getProperty("pwd");
//创建三个原生的连接,都将它们代理
String poolSize = prop.getProperty("poolSize");
int size = Integer.parseInt(poolSize);
for(int i=0;i<size;i++){
final Connection con = DriverManager.getConnection(jdbcurl,nm,pwd);
//对con进行动态代理
Object proxyedObj =
Proxy.newProxyInstance(ConnUtils.class.getClassLoader(),
new Class[]{Connection.class},
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//是否是close方法
if(method.getName().equals("close")){
synchronized (pool) {
pool.addLast((Connection) proxy);
pool.notify();
}
return null;//如果调用的是close则不会调用被代理类的方法。
}
return method.invoke(con, args);
}
});
//将代理对象放到pool中
pool.add((Connection) proxyedObj);
}
} catch (Exception e) {
e.printStackTrace();
}
} public static Connection getConn(){
synchronized (pool) {
if(pool.size()==0){ //如果连接池中没有连接则进入等待池中等待
try {
pool.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
return getConn();
}else{ //如果连接池中有连接则将连接分配出去。
Connection con = pool.removeFirst();
System.err.println("还有几个:"+pool.size());
return con;
}
}
}
}
5.动态代理的核心类。
(1)Proxy类:提供用于创建动态代理类和实例的动态方法,它还是由这些方法创建的所有动态代理类的超类。
(2)InvocationHandler接口:是代理实例的调用处理程序实现的接口。
6.代理的任务
(1)在内存中创建某个接口的子类。
(2)拦截所有在代理上执行的方法。
三、联系人管理小练习。
源代码:https://github.com/kdyzm/day15
【Java EE 学习 15】【自定义数据库连接池之动态代理的使用】的更多相关文章
- [javaEE] 数据库连接池和动态代理
实现javax.sql.DataSource接口 实现Connection getConnection()方法 定义一个静态的成员属性LinkedList类型作为连接池,在静态代码块中初始化5条数据库 ...
- Java EE开发平台随手记5——Mybatis动态代理接口方式的原生用法
为了说明后续的Mybatis扩展,插播一篇广告,先来简要说明一下Mybatis的一种原生用法,不过先声明:下面说的只是Mybatis的其中一种用法,如需要更深入了解Mybatis,请参考官方文档,或者 ...
- 【Java EE 学习 16 上】【dbcp数据库连接池】【c3p0数据库连接池】
一.回顾之前使用的动态代理的方式实现的数据库连接池: 代码: package day16.utils; import java.io.IOException; import java.lang.ref ...
- Java Web(九) JDBC及数据库连接池及DBCP,c3p0,dbutils的使用
DBCP.C3P0.DBUtils的jar包和配置文件(百度云盘):点我下载 JDBC JDBC(Java 数据库连接,Java Database Connectify)是标准的Java访问数据库的A ...
- 【Java EE 学习 16 下】【dbutils的使用方法】
一.为什么要使用dbutils 使用dbutils可以极大程度的简化代码书写,使得开发进度更快,效率更高 二.dbutils下载地址 http://commons.apache.org/proper/ ...
- 【Java EE 学习 19】【使用过滤器实现全站压缩】【使用ThreadLocal模式解决跨DAO事务回滚问题】
一.使用过滤器实现全站压缩 1.目标:对网站的所有JSP页面进行页面压缩,减少用户流量的使用.但是对图片和视频不进行压缩,因为图片和视频的压缩率很小,而且处理所需要的服务器资源很大. 2.实现原理: ...
- Java EE学习——Quartz的Cron表达式
经历过低谷后,还是要好好学习,越失落会越来越落后. 今天写一下Cron表达式的用法,虽然是之前自己写的,也过了挺长一段时间,这次就拿出来作为回顾吧. Cron表达式是Quartz的精髓(个人觉得),比 ...
- 【转】JDBC学习笔记(8)——数据库连接池(dbcp&C3P0)
转自:http://www.cnblogs.com/ysw-go/ JDBC数据库连接池的必要性 一.在使用开发基于数据库的web程序时,传统的模式基本是按一下步骤: 1)在主程序(如servlet/ ...
- 第77节:Java中的事务和数据库连接池和DBUtiles
第77节:Java中的事务和数据库连接池和DBUtiles 前言 看哭你,字数:8803,承蒙关照,谢谢朋友点赞! 事务 Transaction事务,什么是事务,事务是包含一组操作,这组操作里面包含许 ...
随机推荐
- fedora22切换用户windows分区不能自动挂载
新建立一个用户后,然后登陆后,再次登出,登陆原来的账户windows分区不能自动挂载
- maven安装和配置
一.下载maven maven下载页 里面有一些版本区别,binary比较小,适合直接在项目中使用,source带了源代码,windows系统下载zip后缀的 apache-maven-3.3.9-b ...
- java环境配置
一.下载安装sdk jdk和jre的区别: jdk:是编译环境(编译器),把java文件编译成class文件 jre:是运行环境(运行器),执行class文件需要使用jre eclipse开发出jav ...
- JQuery 实现标题与内容相呼应样式
效果图如下:鼠标移到标题上,标题下面显示标题对应的内容.实现的方法如下: 1.引入css和js文件 <link href="public/CSS/StyleSheet.css" ...
- WinForm------GridControl添加底部合计框
1.在GridView属性中找到"OptionsView" => "ShowFooter" = true 2.打开编辑器,如图 . 3.获取统计数据(注意 ...
- 再次认识ASP.NET MVC
MVC, V,就是View.视图 M,只应该是ViewModel.视图模型 C,Controller.控制器 我们需要怎么看待并使用这三者. 从你敲入url,我们可以做为入口. 当你敲入url并按了回 ...
- 逆向工程学习第三天--另外一个ShellCode
上周自己打造的添加用户的shellcode太长,不过当时主要目的是为了锻炼手动asm,熟悉一些复杂的参数类型如何手动进行构造,然后通过堆栈传递. 接下来就打造一个弹计算器的shellcode来进行接下 ...
- awk删除文件第一列
awk删除文件第一列 1.采用awk awk '{$1="";print $0}' file 2.采用sed sed -e 's/[^]* //' file sort -R fil ...
- Google map markers
现已被屏蔽 http://mabp.kiev.ua/2010/01/12/google-map-markers/ Надо по немногу отходить от празднывания но ...
- 面试题目——《CC150》位操作
面试题5.1:给定两个32位的整数N与M,以及表示比特位置的i与j.编写一个方法,将M插入N,使得M从N的第j位开始,到第i位结束.假定从j位到i位足以容纳M,也即若M=10011,那么j与i之间至少 ...