当前位置:   article > 正文

Spring 数据源_java spring datesource

java spring datesource

基于Spring 5.2.6.RELEASE

1、java数据源

1.1、DataSource 接口

public interface DataSource  extends CommonDataSource, Wrapper {
  //获取数据源连接
  Connection getConnection() throws SQLException;
  //重载方法,根据用户名密码获取数据源连接
  Connection getConnection(String username, String password)
    throws SQLException;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

DataSource 接口继承了 CommonDataSource 接口。

1.2、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;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

数据源最重要的是获取链接的方法。个人认为,分析任何数据源产品,从getConnection()入手比较好。

2、Spring的数据源

2.1、DriverManagerDataSource 数据源实现类

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);
		}
	}
	//...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

DriverManagerDataSource 继承了 AbstractDriverBasedDataSource,数据源的属性在这里定义。

2.2、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;
	}
	//获取链接方法,下面单独写。
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

AbstractDriverBasedDataSource 里面定义了数据源的一些属性,AbstractDriverBasedDataSource 继承了 AbstractDataSource,AbstractDataSource 继承了 DataSource。

2.3、AbstractDataSource

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);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

3、获取数据源连接

AbstractDriverBasedDataSource 重写了 java的DataSource获取链接的方法。

//org.springframework.jdbc.datasource.AbstractDriverBasedDataSource#getConnection()
@Override
public Connection getConnection() throws SQLException {
    //委派
    return getConnectionFromDriver(getUsername(), getPassword());
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
//org.springframework.jdbc.datasource.AbstractDriverBasedDataSource#getConnection
@Override
public Connection getConnection(String username, String password) throws SQLException {
    //委派
    return getConnectionFromDriver(username, password);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
//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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

上面的获取连接的方法委派给了这个抽象方法,具体方法由子类实现

//org.springframework.jdbc.datasource.AbstractDriverBasedDataSource#getConnectionFromDriver
protected abstract Connection getConnectionFromDriver(Properties props) throws SQLException;

  • 1
  • 2
  • 3

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);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
//org.springframework.jdbc.datasource.DriverManagerDataSource#getConnectionFromDriverManager
protected Connection getConnectionFromDriverManager(String url, Properties props) throws SQLException {
    //委派给java本身
    return DriverManager.getConnection(url, props);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
//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()));
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
//所有注册的数据源驱动,写时复制,
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");
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

可以看出,Spring的数据源也是实现了java的数据源接口,然后重写java DataSource 的 getConnection 方法,最终委派给 Driver,即数据源驱动去获取链接。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/954977
推荐阅读
相关标签
  

闽ICP备14008679号