【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事务,什么是事务,事务是包含一组操作,这组操作里面包含许 ...
随机推荐
- [转]ExtJs:xtype的含义
原文地址:http://www.cnblogs.com/timy/archive/2010/08/13/1799111.html 根据我在EXT论坛上的观察,xtype用起来的时候疑惑会比较多.甚至有 ...
- Python删除指定时间的文件
import os import time import sys from xml.dom import minidom, Node from xml.dom.minidom import parse ...
- python对缓存(memcached,redis)的操作
1.Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的 ...
- python变量
1. 系统变量 (1) '__doc__' 文件注释,在py中代码最上方""" """里面一般写注释,系统会把文件注释自动存放在'__doc ...
- 第二轮冲刺-Runner站立会议04
今天:查看gridview与baseadapter的连接 明天准备做什么:继续gridview与baseadapter适配器 遇到的困难:暂无
- ecshop 后台时间调用
<script type="text/javascript" src="../js/calendar.php?lang={$cfg_lang}">& ...
- Solr学习总结(七)Solr搜索引擎的整体架构
经过前面一段时间的努力,终于把我所知道的关于solr 的内容都总结完了.前面讲到了solr 的安装配置,web管理后台的使用,solr 的查询参数和查询语法,还说到了solr的客户端 solrnet ...
- Oracle开机自启动
linux下启动oracle su - oracle #用oracle用户登陆 sqlplus /nolog conn /as sysdba startup exit lsnrctl start ex ...
- php判断str是否是xml格式
function xml_parser($str){ $xml_parser = xml_parser_create(); if(!xml_parse($xml_parser,$str,true)){ ...
- golang笔记——string
任何语言中,字符串操作API都是非常重要的,有些还是熟记比较好,当然如果记不住可以去看源码文件,不得不说GO语言源码看起来非常舒服. 可以使用反引号代替双引号,来表示原生的字符串,即不进行转义,尤其适 ...