在是使用spring时候,常常配置数据源,
<bean id="dataSource"
class ="org.springframework.jdbc.datasource.DriverManagerDataSoruce">
<property name="driverClassName" value="org.apache.derby.jdbc.ClinetDriver">
<property name="url" value="jdbc:derby://localhost:1527/news;create=true">
<property name="username" value="admin">
<property name="password" value="admin">
</bean>
在配置文件中共有四个需要注入的属性,在org.springframework.jdbc.datasource.DriverManagerDataSoruce这个类
中,共有5个属性
private String driverClassName;
private String url;
private String username;
private String password;
private Properties connectionProperties;
其实用构造方法注入的方式也是可以的,因为spring除了生成setter方法外,也给我们提供了构造函数,
public DriverManagerDataSource(String driverClassName, String url, String username, String password)
throws CannotGetJdbcConnectionException {
setDriverClassName(driverClassName);
setUrl(url);
setUsername(username);
setPassword(password);
}
其中的前四个是数据库连接的基本配置,而最后一个connectionProperties是通过配置文件properity读取数据库的连接配置,
看DriverManagerDataSoruce这个类是如何获取connection连接 就明白了
protected Connection getConnectionFromDriverManager(String url, Properties props)
throws SQLException {
if (logger.isDebugEnabled()) {
logger.debug("Creating new JDBC Connection to [" + url + "]");
}
return DriverManager.getConnection(url, props);
}
protected Connection getConnectionFromDriverManager(String username, String password)
throws SQLException {
Properties props = new Properties(getConnectionProperties());
if (username != null) {
props.setProperty("user", username);
}
if (password != null) {
props.setProperty("password", password);
}
return getConnectionFromDriverManager(getUrl(), props);
}
其中DriverManagerDataSoruce这个类本身又继承至AbstractDataSource这个类,AbstractDataSource这个类继承至
javax.sql.DataSource类,在AbstractDataSource这个类中,什么也没做,只是一个简单的抽象类,并有几个简单的方
法,
public abstract class AbstractDataSource implements DataSource {
protected final Log logger = LogFactory.getLog(getClass());
/**
* Returns 0: means use default system timeout.
*/
public int getLoginTimeout() throws SQLException {
return 0;
}
public void setLoginTimeout(int timeout) throws SQLException {
throw new UnsupportedOperationException("setLoginTimeout");
}
/**
* LogWriter methods are unsupported.
*/
public PrintWriter getLogWriter() {
throw new UnsupportedOperationException("getLogWriter");
}
/**
* LogWriter methods are unsupported.
*/
public void setLogWriter(PrintWriter pw) throws SQLException {
throw new UnsupportedOperationException("setLogWriter");
}
}
返回来再看DriverManagerDataSource这个类,其实DriverManagerDataSource并不是一个有效的数据源实现,因为每
次被请求的时候都要为客户端打开一个新的连接。 spring提供了另一种实现是SingleConnectionDataSource,顾名思义,它只保留单一连接,总是重用该连接,永不关闭,这个显然不适合多线程环境。
public class SingleConnectionDataSource extends DriverManagerDataSource
implements SmartDataSource, DisposableBean
SingleConnectionDataSource 本身又具有DriverManagerDataSource的所有属性,所以可以说
SingleConnectionDataSource 是DriverManagerDataSource的扩展和延伸,可以看到SingleConnectionDataSource 除
了继承DriverManagerDataSource外,本身又实现了俩个借口SmartDataSource和DisposableBean,下面先分别介绍这俩
个接口然后返回来介绍SingleConnectionDataSource 这个类.
SmartDataSource继承至javax.sql.DataSource这个接口,只是提供了一个方法
boolean shouldClose(Connection con);定义是否可以关闭连接。
DisposableBean接口也是定义了一个方法 void destroy() throws Exception;
方法的作用是在被调用BeanFactory时销毁一个连接,
返回看SingleConnectionDataSource类,先看这俩个接口是如何实现 。
/**
* This is a single Connection: Do not close it when returning to the "pool".
*/
public boolean shouldClose(Connection con) {
synchronized (this.connectionMonitor) {
return (con != this.connection && con != this.target);
}
}
看这个实现就明白,不用多说。在看另一个实现类
public void destroy() {
synchronized (this.connectionMonitor) {
closeConnection();
}
}
其中synchronized (this.connectionMonitor) 是同步的作用,防止死锁。
connectionMonitor的定义很简单
/** Synchronization monitor for the shared Connection */
private final Object connectionMonitor = new Object();
/**
* Close the underlying shared Connection.
*/
private void closeConnection() {
if (this.target != null) {
try {
this.target.close();
}
catch (Throwable ex) {
logger.warn("Could not close shared JDBC Connection", ex);
}
}
}