尝试深入数据源与连接池的JAVA(mgds4j)实现
梦来梦往 2014-12-01 14:01
目录
1.摘要
我是这样来理解数据源与连接池这个名词的,数据源是使用连接池技术来缓存数据库连接资源对外工具包接口,连接池是一种在传统的jdbc上封装多个数据库Connection,来提高数据库访问效率的解决方案,也就是技术。
目前,比较流行的数据源有:
Apache的DBCP数据源,
开源牛人的C3P0数据源,
Alibaba的Druid数据源,
Sourceforge的proxool数据源......
由于,在使用spring来开发JAVAWeb项目时,我们都可以很方便的加入各种数据源。但是,我在写一些比较小的JAVA项目时,却发现集成数据源不是很方便,或者说,本来就是一个小项目,加入一个数据源就比源项目要大的多,这样就有一点的不尝试的感觉。
而且,我也不想再在自己的项目中重复造同样的轮子,使用每次得到conncection用完之后,就和数据库断开连接的方式(这样效率不高,时间都浪费在获取连接的部分了)。
所以,我就有了自己写一个适合JAVA项目使用的精简版的数据源,取名为mgds4j,全称是mgang datasource for java。
2.mgds4j的设计原理
在使用到数据源的时候,对数据源进行初始化。
---初始化连接池部分,默认5个connection连接放到连接池向量中。
---要使用数据库连接,可以从数据源中获取,用完后归还到连接池中。
---当连接池中的可用连接数为0时,还有请求要使用连接的话,线程会等待2秒(默认);
如果等待完成后,连接池中有可用的数据源连接就获取。
如果等待完成后,连接池中还是没有可用的连接,数据源就会按照连接池的自动增长
属性来动态的创建数据库连接并放回到连接池中,这时连接池的总大小也会随之增 大。
切记,在程序退出时,请调用数据源的destory方法来关闭数据源和连接池,释放资源。
3.mgds4j的JAVA实现
这个项目,我是放在github上来管理的。目前完成了基本的功能,有多个版本,v2.1是最终版。这里,我就慢慢地说一下实现的各个版本的细微差别。
3.1.mgds4j V1.0
上图是第一个版本v1.0的项目目录结构,这里我有两个住文件MgDataSource.java和MgConnectionPool.java。很明显,我在写第一个版本的时候,对数据源与连接池的概念理解的不是很清晰,把他们分成了两个东西。但是功能都还是实现了,只不过多个一层。
接着看source floder的config中的mgds4j.properties文件,很明显这个版本是用properties文件来做配置文件的。
Mgds4j.properties文件内容如下:
#meigang datasource for java
#梦来梦往 自己实现的数据源连接池 工具,自命名为mgds4j
#数据库驱动
mgds4j.driverName = com.mysql.jdbc.Driver
#数据库连接url
mgds4j.url = jdbc:mysql://localhost:3306/mgds4j?useUnicode=true&characterEncoding=UTF-8
#数据库用户名
mgds4j.userName = root
#数据库密码
mgds4j.password = root
#自动增长的大小,默认为1
mgds4j.autoIncrement = 1
#连接池的大小,默认为5个connection
mgds4j.poolSize = 5
并且测试通过。
这里,大家不要担心,我是在github上写的,所以是开源的,欢迎大家来fork。
Github:https://github.com/mg0324/mgds4j.git
gitOsChina:https://git.oschina.net/mgang/mgds4j.git
3.2.mgds4j v1.1
这个版本较v1.0没有太大的改动,只是将等待时间抽成了参数,可以在配置文件中配置了。
#v1.1,等待时间,单位是ms(毫秒)
mgds4j.waitTimeOut = 3000
3.3.mgds4j v2.0
V2.0升级日志:
---将两个主文件合并成一个主文件MgDataSource.java,使得更契合数据源和连接池的 概念。
项目目录结构:
测试通过。
3.4.mgds4j v2.1
V2.1升级日志:
---考虑到主流的配置文件是xml,故将配置文件修改成mgds4j.xml,使用dom4j解析。
---使数据源单例化,从MgDataSourceFactory工厂中获取,使用反射机制来实现。
项目目录结构:
测试通过。
细节部分:
Mgds4j.xml配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<factory>
<!-- 数据源节点,name属性是放在DataSourceFactory中的key,class属性是用来反射生成MgDataSource对象的
-->
<dataSource name="ds" class="com.mgang.mgds4j.core.MgDataSource">
<!-- property节点,就是配置的MgDataSource的属性 -->
<property key="driverName" value="com.mysql.jdbc.Driver" type="string"></property>
<property key="url" type="string"
value="jdbc:mysql://localhost:3306/mgds4j?useUnicode=true&characterEncoding=UTF-8"></property>
<property key="userName" value="root" type="string"></property>
<property key="password" value="root" type="string"></property>
<property key="autoIncrement" value="1" type="int"></property>
<property key="poolSize" value="5" type="int"></property>
<property key="waitTimeOut" value="3000" type="int"></property>
</dataSource>
</factory>
反射细节:
//通过调用static函数getInstance来得到单例对象
Class dsClass = Class.forName(clazz);
ds = (MgDataSource) dsClass.getMethod("getInstance", null).invoke(dsClass, null);
factory.put(name, ds);
//得到dataSource下的property节点
Iterator ps = dsElement.elementIterator("property");
while(ps.hasNext()){
Element propertyElement = (Element) ps.next();
String key = propertyElement.attributeValue("key");
String value = propertyElement.attributeValue("value");
String type = propertyElement.attributeValue("type");
if(type.equals("string")){
Method m = MgDataSource.class.getMethod("set"+UpperFirst(key),String.class);
m.invoke(ds, value);
}else if(type.equals("int")){
Method m = MgDataSource.class.getMethod("set"+UpperFirst(key),int.class);
m.invoke(ds, Integer.parseInt(value.trim()));
}
}
单例细节:
private static MgDataSource mgds = null;
private MgDataSource(){
}
/**
* 得到MgDataSource的单例对象
* @return
*/
public static MgDataSource getInstance(){
if(null == mgds){
mgds = new MgDataSource();
}
return mgds;
}
工厂模式细节:
//创建工厂
MgDataSourceFactory.build();
//从工厂得到数据源
ds = MgDataSourceFactory.getMgDataSource("ds");
4.mgds4j的问题
4.1.关于数据源连接池的关闭?
答:向c3p0数据源,在配置的时候就会在dataSource节点上配置一个destory属性来关闭数据源。Destory=”close”,意思就是在项目关闭的时候调用数据源的close方法来关闭数据源。
所以,连接池的关闭应该是在程序退出或者是项目关闭的时候关闭的。Mgds4j提供了destory方法来关闭数据源的连接池,来释放资源。(手动添加)
未完待续...
关于 梦来梦往:
QQ:1092017732
网易博客:http://blog.163.com/mg_blog/
Github:https://github.com/mg0324/mgds4j
gitOsChina:http://git.oschina.net/mgang/mgds4j
在线展示:http://mg0324.github.io/mgds4j/