赞
踩
基于Spring 5.2.6.RELEASE
public interface DataSource extends CommonDataSource, Wrapper {
//获取数据源连接
Connection getConnection() throws SQLException;
//重载方法,根据用户名密码获取数据源连接
Connection getConnection(String username, String password)
throws SQLException;
}
DataSource 接口继承了 CommonDataSource 接口。
public interface CommonDataSource {
java.io.PrintWriter getLogWriter() throws SQLException;
void setLogWriter(java.io.PrintWriter out) throws SQLException;
void setLoginTimeout(int seconds) throws SQLException;
int getLoginTimeout() throws SQLException;
//1.7 新增方法
public Logger getParentLogger() throws SQLFeatureNotSupportedException;
}
数据源最重要的是获取链接的方法。个人认为,分析任何数据源产品,从getConnection()入手比较好。
public class DriverManagerDataSource extends AbstractDriverBasedDataSource { public DriverManagerDataSource() { } public DriverManagerDataSource(String url) { setUrl(url); } public DriverManagerDataSource(String url, String username, String password) { setUrl(url); setUsername(username); setPassword(password); } public DriverManagerDataSource(String url, Properties conProps) { setUrl(url); setConnectionProperties(conProps); } //初始化数据库驱动 public void setDriverClassName(String driverClassName) { Assert.hasText(driverClassName, "Property 'driverClassName' must not be empty"); String driverClassNameToUse = driverClassName.trim(); try { Class.forName(driverClassNameToUse, true, ClassUtils.getDefaultClassLoader()); } catch (ClassNotFoundException ex) { throw new IllegalStateException("Could not load JDBC driver class [" + driverClassNameToUse + "]", ex); } if (logger.isDebugEnabled()) { logger.debug("Loaded JDBC driver: " + driverClassNameToUse); } } //... }
DriverManagerDataSource 继承了 AbstractDriverBasedDataSource,数据源的属性在这里定义。
public abstract class AbstractDriverBasedDataSource extends AbstractDataSource { @Nullable private String url; @Nullable private String username; @Nullable private String password; @Nullable private String catalog; @Nullable private String schema; @Nullable private Properties connectionProperties; public void setUrl(@Nullable String url) { this.url = (url != null ? url.trim() : null); } @Nullable public String getUrl() { return this.url; } public void setUsername(@Nullable String username) { this.username = username; } @Nullable public String getUsername() { return this.username; } public void setPassword(@Nullable String password) { this.password = password; } @Nullable public String getPassword() { return this.password; } public void setCatalog(@Nullable String catalog) { this.catalog = catalog; } @Nullable public String getCatalog() { return this.catalog; } public void setSchema(@Nullable String schema) { this.schema = schema; } @Nullable public String getSchema() { return this.schema; } public void setConnectionProperties(@Nullable Properties connectionProperties) { this.connectionProperties = connectionProperties; } @Nullable public Properties getConnectionProperties() { return this.connectionProperties; } //获取链接方法,下面单独写。 }
AbstractDriverBasedDataSource 里面定义了数据源的一些属性,AbstractDriverBasedDataSource 继承了 AbstractDataSource,AbstractDataSource 继承了 DataSource。
public abstract class AbstractDataSource implements DataSource { /** Logger available to subclasses. */ protected final Log logger = LogFactory.getLog(getClass()); @Override public int getLoginTimeout() throws SQLException { return 0; } @Override public void setLoginTimeout(int timeout) throws SQLException { throw new UnsupportedOperationException("setLoginTimeout"); } @Override public PrintWriter getLogWriter() { throw new UnsupportedOperationException("getLogWriter"); } @Override public void setLogWriter(PrintWriter pw) throws SQLException { throw new UnsupportedOperationException("setLogWriter"); } @Override @SuppressWarnings("unchecked") public <T> T unwrap(Class<T> iface) throws SQLException { if (iface.isInstance(this)) { return (T) this; } throw new SQLException("DataSource of type [" + getClass().getName() + "] cannot be unwrapped as [" + iface.getName() + "]"); } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { return iface.isInstance(this); } @Override public Logger getParentLogger() { return Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); } }
AbstractDriverBasedDataSource 重写了 java的DataSource获取链接的方法。
//org.springframework.jdbc.datasource.AbstractDriverBasedDataSource#getConnection()
@Override
public Connection getConnection() throws SQLException {
//委派
return getConnectionFromDriver(getUsername(), getPassword());
}
//org.springframework.jdbc.datasource.AbstractDriverBasedDataSource#getConnection
@Override
public Connection getConnection(String username, String password) throws SQLException {
//委派
return getConnectionFromDriver(username, password);
}
//org.springframework.jdbc.datasource.AbstractDriverBasedDataSource#getConnectionFromDriver protected Connection getConnectionFromDriver(@Nullable String username, @Nullable String password) throws SQLException { //连接属性 Properties mergedProps = new Properties(); Properties connProps = getConnectionProperties(); if (connProps != null) { mergedProps.putAll(connProps); } if (username != null) { mergedProps.setProperty("user", username); } if (password != null) { mergedProps.setProperty("password", password); } //委派 Connection con = getConnectionFromDriver(mergedProps); if (this.catalog != null) { con.setCatalog(this.catalog); } if (this.schema != null) { con.setSchema(this.schema); } return con; }
上面的获取连接的方法委派给了这个抽象方法,具体方法由子类实现
//org.springframework.jdbc.datasource.AbstractDriverBasedDataSource#getConnectionFromDriver
protected abstract Connection getConnectionFromDriver(Properties props) throws SQLException;
DriverManagerDataSource 实现的获取链接方法
//org.springframework.jdbc.datasource.DriverManagerDataSource#getConnectionFromDriver
@Override
protected Connection getConnectionFromDriver(Properties props) throws SQLException {
String url = getUrl();
Assert.state(url != null, "'url' not set");
if (logger.isDebugEnabled()) {
logger.debug("Creating new JDBC DriverManager Connection to [" + url + "]");
}
//继续委派
return getConnectionFromDriverManager(url, props);
}
//org.springframework.jdbc.datasource.DriverManagerDataSource#getConnectionFromDriverManager
protected Connection getConnectionFromDriverManager(String url, Properties props) throws SQLException {
//委派给java本身
return DriverManager.getConnection(url, props);
}
//java.sql.DriverManager#getConnection(java.lang.String, java.util.Properties)
public static Connection getConnection(String url,java.util.Properties info) throws SQLException {
//委派
return (getConnection(url, info, Reflection.getCallerClass()));
}
//所有注册的数据源驱动,写时复制, private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>(); //java.sql.DriverManager#getConnection private static Connection getConnection(String url, java.util.Properties info, Class<?> caller) throws SQLException { ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; synchronized(DriverManager.class) { // synchronize loading of the correct classloader. if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); } } if(url == null) { throw new SQLException("The url cannot be null", "08001"); } println("DriverManager.getConnection(\"" + url + "\")"); SQLException reason = null; //遍历所有注册的数据库驱动,获取匹配的数据源。 for(DriverInfo aDriver : registeredDrivers) { //找到匹配的数据源 if(isDriverAllowed(aDriver.driver, callerCL)) { try { println(" trying " + aDriver.driver.getClass().getName()); //获取链接,这里也是各个数据源产品重写的地方,比如druid Connection con = aDriver.driver.connect(url, info); //获取到连接,返回 if (con != null) { // Success! println("getConnection returning " + aDriver.driver.getClass().getName()); return (con); } } catch (SQLException ex) { if (reason == null) { reason = ex; } } } else { println(" skipping: " + aDriver.getClass().getName()); } } // if we got here nobody could connect. if (reason != null) { println("getConnection failed: " + reason); throw reason; } println("getConnection: no suitable driver found for "+ url); throw new SQLException("No suitable driver found for "+ url, "08001"); }
可以看出,Spring的数据源也是实现了java的数据源接口,然后重写java DataSource 的 getConnection 方法,最终委派给 Driver,即数据源驱动去获取链接。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。