在是使用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);
			}
		}
	}