IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Spring 数据源 -> 正文阅读

[Java知识库]Spring 数据源

基于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;
}

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

数据源最重要的是获取链接的方法。个人认为,分析任何数据源产品,从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);
		}
	}
	//...
}

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;
	}
	//获取链接方法,下面单独写。
}

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

3、获取数据源连接

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,即数据源驱动去获取链接。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 10:59:34  更:2022-09-13 11:02:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:31:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码