从源码理解 Spring 如何管理数据库连接

本文详细探讨了 Spring 如何通过 JdbcTemplate 和 DataSourceUtils 管理数据库连接,重点解析了 DataSourceUtils 获取和释放 Connection 的过程,以及 TransactionSynchronizationManager 在线程绑定和资源管理中的作用。通过对源码的分析,揭示了 Spring 在事务上下文中如何确保数据连接的正确使用和释放,从而避免连接泄漏问题。
摘要由CSDN通过智能技术生成

1 - 引言

在了解 Spring 中数据库连接池的实现机制时,看到一些新知识,但是单纯的文字或实验描述并不能让我深入了解这些知识。

Spring DAO 对所有支持的数据访问技术框架都使用模板化技术进行了薄层的封装。只要您的程序都使用 Spring DAO 模板(如 JdbcTemplate、HibernateTemplate 等)进行数据访问,一定不会存在数据连接泄漏的问题 ―― 这是 Spring 给予我们郑重的承诺!因此,我们无需关注数据连接(Connection)及其衍生品(Hibernate 的 Session 等)的获取和释放的操作,模板类已经通过其内部流程替我们完成了,且对开发者是透明的。
当 Spring 事务方法运行时,就产生一个事务上下文,该上下文在本事务执行线程中针对同一个数据源绑定了一个唯一的数据连接(或其衍生品),所有被该事务上下文传播的方法都共享这个数据连接。这个数据连接从数据源获取及返回给数据源都在 Spring 掌控之中,不会发生问题。如果在需要数据连接时,能够获取这个被 Spring 管控的数据连接,则使用者可以放心使用,无需关注连接释放的问题。1

偶然看到上面关于Spring中数据库连接的一段描述,字面上挺好理解的。但背下来只能拿来撑场面,没什么意思,还是需要自己亲自查看一番,知其然还要知其所以然。

这次我们不考虑 MyBatis 或者 Hibernate 之类的持久层框架怎么使用数据库连接池,研究下 Spring 自己是怎么管理数据库连接的。


2 - Spring 的 DAO 工具类

2.1 JdbcTemplate

在 Spring 下做持久层操作,不使用持久层框架的情况下一般会选择使用 JdbcTemplate 这种模版类,它底层封装了 JDBC,避免了直接书写 JDBC 的麻烦,也一定程度上帮助管理数据库连接,使程序员更加专注于业务查询。使用方法是将其配置为 bean 之后进行注入,比如下面这样:

	<bean id = "jdbcTemplate" 
 		class="org.springframework.jdbc.core.JdbcTemplate">
 		<!-- 指定数据源 -->
        <property name="dataSource" ref="dataSource"/> 
    </bean>

那么我们首先考察一下 JdbcTemplate 的核心方法 execute(),它是执行查询的关键,这个方法有众多的重载形式,这里截取其中一个。留意到在 execute() 内部获取和释放连接的关键代码如下:

	public <T> T execute(ConnectionCallback<T> action){
   
		...
        Connection con = DataSourceUtils.getConnection(this.getDataSource());
		...
        try {
   
            ...
        } catch (SQLException var8) {
   
            DataSourceUtils.releaseConnection(con, this.getDataSource());
            ...
        } finally {
   
            DataSourceUtils.releaseConnection(con, this.getDataSource());
        }
        return var4;
    }	
2.2 DataSourceUtils 获取 Connection

在上一节代码可以看到 DataSourceUtils 的身影,它负责管理连接的获取和释放,看来这就是我们应该研究的对象了。关于 DataSourceUtils 这个类,查询 Spring 4.3 的文档获得这样的解释:

Helper class that provides static methods for obtaining JDBC Connections from a DataSource. Includes special support for Spring-managed transactional Connections, e.g. managed by DataSourceTransactionManager or JtaTransactionManager. 2

翻译过来就是提供一些静态方法从数据源获取 JDBC 连接,同时提供对 Spring 管理的(加入了)事务的(数据库)连接的一些支持。这里我们看到了事务与连接这两个概念发生了关联,正和我们前面提到的事务上下文会绑定一条数据库连接。

我们需要研究怎么获取数据库连接就绕不开 DataSourceUtils.getConnection() 这个方法,官方文档解释:

Obtain a Connection from the given DataSource. Translates SQLExceptions into the Spring hierarchy of unchecked generic data access exceptions, simplifying calling code and making any exception that is thrown more meaningful.
Is aware of a corresponding Connection bound to the current thread, for example when using DataSourceTransactionManager. Will bind a Connection to the thread if transaction synchronization is active, e.g. when running within a JTA transaction). 2

大意是从给定的数据源获取连接,做一些异常处理,如果当前事务是活跃的,会将一条连接绑定到当前的线程。那么线程和连接的绑定是怎么做的呢?我们还是看一下源代码吧。

	public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
   
        try {
   
            return doGetConnection(dataSource); // 实际调用方法 doGetConnection
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值