数据库连接池实现原理
实现原理是用动态代理技术
编写连接池需实现java.sql.DataSource接口,
DataSource接口中定义了两个重载的getConnection方法:
Connection getConnection()
Connection getConnection(String username, String password)
public class JdbcPool implements DataSource {
private static String driver;
private static String url;
private static String username;
private static String password;
static{
try {
Properties prop = new Properties();
InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
prop.load(in);
driver = prop.getProperty("driver");
url = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password");
Class.forName(driver);
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
private static LinkedList pool = new LinkedList();
private static int poolsize = 10;
//问题:每次newJdbcPoll都会建立10个链接,可使用单态设计模式解决此类问题
public JdbcPool(){
for(int i=0;i
try {
Connection conn = DriverManager.getConnection(url,username,password);
pool.add(conn);
System.out.println(conn + "被加到池里面了!!!");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/*
* 这里使用动态代理技术返回一个假的Connection,当dao调用假connection的任何方法时,该方法体内会调用InvocationHandler.invoke方法
* 在invoke方法体内,发现dao调用的是close方法,则把链接还到池里,否则,调用真connection的对应方法。
* (non-Javadoc)
* @see javax.sql.DataSource#getConnection()
*/
public Connection getConnection() throws SQLException { //spring aop
if(pool.size()>0){
final Connection conn = pool.removeFirst();
System.out.println(conn + "从池里面取出去了!!!");
return (Connection) Proxy.newProxyInstance(JdbcPool.class.getClassLoader(),conn.getClass().getInterfaces(), new InvocationHandler(){
//proxy为代理对象 method为要调用的方法 args为方法的参数
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equals("close")){
pool.addFirst(conn);
System.out.println(conn + "被还到池里面了!!");
return null;
}else{
return method.invoke(conn, args);
}
}
});
}
throw new RuntimeException("对不起,池里没有资源了!!!");
}
public Connection getConnection(String arg0, String arg1)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public int getLoginTimeout() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
public void setLogWriter(PrintWriter arg0) throws SQLException {
// TODO Auto-generated method stub
}
public void setLoginTimeout(int arg0) throws SQLException {
// TODO Auto-generated method stub
}
//public Jdbcpool
}
一般实现第一个就可了,数据库的信息都 是通过配置文件来实现的,
通过加载配置文件就可以,取得与数据库的连接
实现DataSource接口,并实现连接池功能的步骤:
1.在DataSource构造函数中批量创建与数据库的连接,并把创建的连接加入LinkedList对象中
因为LinkedList 是用链表实现的,对于增删实现起来比较容易
因为每从池中取出一个连接,都要将这个对象从池不删除,当返回时就要添加回去
2.实现getConnection方法,让getConnection方法每次调用时,
从LinkedList中取一个Connection返回给用户(即要从池中删除一个对象)
3.当用户使用完Connection,调用Connection.close()方法时,
Collection对象应保证将自己返回到LinkedList中
(用户一般都会调用Connection的close方法来关闭连接,从而不能将这个连接返回给池,
所以这里采用了动态代理技术:赤获取用户关闭连接的操作,当获取到时而不是将其给关闭,
而是将这个连接(对象)添加到池中)
注:
** 这里使用动态代理技术返回一个假的Connection,
当dao调用假connection的任何方法时,该方法体内会调用InvocationHandler.invoke方法
** 在invoke方法体内,发现dao调用的是close方法,则把链接还到池里,
否则,调用真connection的对应方法。
开源的数据库连接池(数据源)
都提供DataSoruce的实现,即连接池的实现
DBCP 数据库连接池 C3P0 数据库连接池
DBCP 是 Apache 软件基金组织下的开源连接池实现,使用DBCP数据源
Commons-dbcp.jar:连接池的实现
Commons-pool.jar:连接池实现的依赖库
它用到了一个配置文件dbcpconfig.properties(放在类路径下)
用BaseDataSourceFactory 对象 装载这个配置文件
private static DataSource dataSource;
static {
try {
InputStream in = JdbcUtil.class.getClassLoader()
.getResourceAsStream("dbcpconfig.properties");
Properties prop = new Properties();
prop.load(in);
BasicDataSourceFactory factory = new BasicDataSourceFactory();
dataSource = factory.createDataSource(prop);
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
在Tomcat 下实现数据库连接池
1.要在META-INF目录下建一个context.xml文件
type="javax.sql.DataSource" username="root" password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/jdbc"
maxActive="8" maxIdle="4"/>
(这是将数据库连接对象绑定到一个名字中去,要用到时就通过这个名字来找这个对象)JNDI
2.还要将数据库驱动的JAR复制到Tomcat的LIB目录下,因为Tomcat起动时就会去初始化连接池
所以就会去找相应的JAR文件,其实这个配置是可以配在Tomcat conf目录下server.xml文件中的
, 为了不改变它原来的配置,所以配置有那也是一样有效的
3.取得连接,通过命名空间
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
dataSource = (DataSource)envCtx.lookup("jdbc/dataSource");
分享到:
2010-09-21 23:11
浏览 6516
评论