spring jdbc 源码 分析
2011-08-11 13:39
417 查看
Collections.unmodifiableMap(map)-------------------------返回一个不可修改的map
转自:http://www.iteye.com/topic/11738
1 如何获得连接
看DataSourceUtils代码
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
protected static Connection doGetConnection(DataSource dataSource, boolean allowSynchronization);
throws SQLException {
ConnectionHolder conHolder = (ConnectionHolder); TransactionSynchronizationManager.getResource(dataSource);;
if (conHolder != null); {
conHolder.requested();;
return conHolder.getConnection();;
}
Connection con = dataSource.getConnection();;
if (allowSynchronization && TransactionSynchronizationManager.isSynchronizationActive();); {
conHolder = new ConnectionHolder(con);;
TransactionSynchronizationManager.bindResource(dataSource, conHolder);;
TransactionSynchronizationManager.registerSynchronization(new ConnectionSynchronization(conHolder, dataSource););;
conHolder.requested();;
}
return con;
}
原来连接是从TransactionSynchronizationManager中获取,如果TransactionSynchronizationManager中已经有了,那么拿过来然后调用conHolder.requested()。否则从原始的DataSource这创建一个连接,放到一个ConnectionHolder,然后再调用TransactionSynchronizationManager.bindResource绑定。
好,我们又遇到两个新的类TransactionSynchronizationManager和ConnectionHolder和。继续跟踪
2 TransactionSynchronizationManager
看其中的一些代码
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
private static ThreadLocal resources = new ThreadLocal();;
public static Object getResource(Object key); {
Map map = (Map); resources.get();;
if (map == null); {
return null;
}
Object value = map.get(key);;
return value;
}
public static void bindResource(Object key, Object value); throws IllegalStateException {
Map map = (Map); resources.get();;
if (map == null); {
map = new HashMap();;
resources.set(map);;
}
map.put(key, value);;
}
原来TransactionSynchronizationManager内部建立了一个ThreadLocal的resources,这个resources又是和一个map联系在一起的,这个map在某个线程第一次调用bindResource时生成。
联系前面的DataSourceUtils代码,我们可以总结出来。
某个线程使用DataSourceUtils,当第一次要求创建连接将在TransactionSynchronizationManager中创建出一个ThreadLocal的map。然后以DataSource作为键,ConnectionHolder为值放到map中。等这个线程下一次再请求的这个DataSource的时候,就从这个map中获取对应的ConnectionHolder。用map是为了解决同一个线程上多个DataSource。
然后我们来看看ConnectionHolder又是什么?
3 对连接进行引用计数
看ConnectionHolder代码,这个类很简单,看不出个所以然,只好再去看父类代码ResourceHolderSupport,我们感兴趣的是这两个方法
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
public void requested(); {
this.referenceCount++;
}
public void released(); {
this.referenceCount--;
}
看得出这是一个引用计数的技巧。原来Spring中对Connection是竟量使用已创建的对象,而不是每次都创建一个新对象。这就是DataSourceUtils中
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
if (conHolder != null); {
conHolder.requested();;
return conHolder.getConnection();;
}
的原因
4 释放连接
完成事物后DataSourceTransactionManager有这样的代码
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
protected void doCleanupAfterCompletion(Object transaction); {
DataSourceTransactionObject txObject = (DataSourceTransactionObject); transaction;
// Remove the connection holder from the thread.
TransactionSynchronizationManager.unbindResource(this.dataSource);;
txObject.getConnectionHolder();.clear();;
//... DataSourceUtils.closeConnectionIfNecessary(con, this.dataSource);;
}
DataSourceUtils
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
protected static void doCloseConnectionIfNecessary(Connection con, DataSource dataSource); throws SQLException {
if (con == null); {
return;
}
ConnectionHolder conHolder = (ConnectionHolder); TransactionSynchronizationManager.getResource(dataSource);;
if (conHolder != null && con == conHolder.getConnection();); {
// It's the transactional Connection: Don't close it.
conHolder.released();;
return;
}
// Leave the Connection open only if the DataSource is our
// special data source, and it wants the Connection left open.
if (!(dataSource instanceof SmartDataSource); || ((SmartDataSource); dataSource);.shouldClose(con);); {
logger.debug("Closing JDBC connection");;
con.close();;
}
}
恍然大悟。如果事物完成,那么就
TransactionSynchronizationManager.unbindResource(this.dataSource);将当前的ConnectionHolder
从TransactionSynchronizationManager上脱离,然后doCloseConnectionIfNecessary。最后会把连接关闭掉。
5 两个辅助类JdbcTemplate和TransactionAwareDataSourceProxy
JdbcTemplate中的execute方法的第一句和最后一句
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
public Object execute(PreparedStatementCreator psc, PreparedStatementCallback action);
throws DataAccessException {
Connection con = DataSourceUtils.getConnection(getDataSource(););;
//其他代码
DataSourceUtils.closeConnectionIfNecessary(con, getDataSource(););;
}
}
作用不言自明了吧
从TransactionAwareDataSourceProxy中获取的连接是这个样子的
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
public Connection getConnection(); throws SQLException {
Connection con = DataSourceUtils.doGetConnection(getTargetDataSource();, true);;
return getTransactionAwareConnectionProxy(con, getTargetDataSource(););;
}
万变不离其宗,不过我们还是看看getTransactionAwareConnectionProxy
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
protected Connection getTransactionAwareConnectionProxy(Connection target, DataSource dataSource); {
return (Connection); Proxy.newProxyInstance(
ConnectionProxy.class.getClassLoader();,
new Class[] {ConnectionProxy.class},
new TransactionAwareInvocationHandler(target, dataSource););;
}
原来返回的是jdk的动态代理。继续看TransactionAwareInvocationHandler
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
public Object invoke(Object proxy, Method method, Object[] args); throws Throwable {
//... if (method.getName();.equals(CONNECTION_CLOSE_METHOD_NAME);); {
if (this.dataSource != null); {
DataSourceUtils.doCloseConnectionIfNecessary(this.target, this.dataSource);;
}
return null;
}
}
TransactionAwareDataSourceProxy会先从DataSourceUtils获取连接。然后将这个连接用jdk的动态代理包一下返回。外部代码如果调用的这个冒牌的Connection,就会先调用TransactionAwareInvocationHandler的invoke,在这个invoke 中,完成原来调用DataSourceUtils的功能。
总结上面的流程
Spring 对DataSource进行事务管理的关键在于ConnectionHolder和TransactionSynchronizationManager。
0.先从TransactionSynchronizationManager中尝试获取连接
1.如果前一步失败则在每个线程上,对每个DataSouce只创建一个Connection
2.这个Connection用ConnectionHolder包装起来,由TransactionSynchronizationManager管理
3.再次请求同一个连接的时候,从TransactionSynchronizationManager返回已经创建的ConnectionHolder,然后调用ConnectionHolder的request将引用计数+1
4.释放连接时要调用ConnectionHolder的released,将引用计数-1
5.当事物完成后,将ConnectionHolder从TransactionSynchronizationManager中解除。当谁都不用,这个连接被close
以上所有都是可以调用DataSourceUtils化简代码,而JdbcTemplate又是调用DataSourceUtils的。所以在Spring文档中要求尽量首先使用JdbcTemplate,其次是用DataSourceUtils来获取和释放连接。至于TransactionAwareDataSourceProxy,那是下策的下策。不过可以将Spring事务管理和遗留代码无缝集成。
所以如某位朋友说要使用Spring的事务管理,但是又不想用JdbcTemplate,那么可以考虑TransactionAwareDataSourceProxy。这个类是原来DataSource的代理。
其次,想使用Spring事物,又不想对Spring进行依赖是不可能的。与其试图自己模拟DataSourceUtils,不如直接使用现成的。
转自:http://www.iteye.com/topic/11738
1 如何获得连接
看DataSourceUtils代码
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
protected static Connection doGetConnection(DataSource dataSource, boolean allowSynchronization);
throws SQLException {
ConnectionHolder conHolder = (ConnectionHolder); TransactionSynchronizationManager.getResource(dataSource);;
if (conHolder != null); {
conHolder.requested();;
return conHolder.getConnection();;
}
Connection con = dataSource.getConnection();;
if (allowSynchronization && TransactionSynchronizationManager.isSynchronizationActive();); {
conHolder = new ConnectionHolder(con);;
TransactionSynchronizationManager.bindResource(dataSource, conHolder);;
TransactionSynchronizationManager.registerSynchronization(new ConnectionSynchronization(conHolder, dataSource););;
conHolder.requested();;
}
return con;
}
protected static Connection doGetConnection(DataSource dataSource, boolean allowSynchronization); throws SQLException { ConnectionHolder conHolder = (ConnectionHolder); TransactionSynchronizationManager.getResource(dataSource);; if (conHolder != null); { conHolder.requested();; return conHolder.getConnection();; } Connection con = dataSource.getConnection();; if (allowSynchronization && TransactionSynchronizationManager.isSynchronizationActive();); { conHolder = new ConnectionHolder(con);; TransactionSynchronizationManager.bindResource(dataSource, conHolder);; TransactionSynchronizationManager.registerSynchronization(new ConnectionSynchronization(conHolder, dataSource););; conHolder.requested();; } return con; }
原来连接是从TransactionSynchronizationManager中获取,如果TransactionSynchronizationManager中已经有了,那么拿过来然后调用conHolder.requested()。否则从原始的DataSource这创建一个连接,放到一个ConnectionHolder,然后再调用TransactionSynchronizationManager.bindResource绑定。
好,我们又遇到两个新的类TransactionSynchronizationManager和ConnectionHolder和。继续跟踪
2 TransactionSynchronizationManager
看其中的一些代码
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
private static ThreadLocal resources = new ThreadLocal();;
public static Object getResource(Object key); {
Map map = (Map); resources.get();;
if (map == null); {
return null;
}
Object value = map.get(key);;
return value;
}
public static void bindResource(Object key, Object value); throws IllegalStateException {
Map map = (Map); resources.get();;
if (map == null); {
map = new HashMap();;
resources.set(map);;
}
map.put(key, value);;
}
private static ThreadLocal resources = new ThreadLocal();; public static Object getResource(Object key); { Map map = (Map); resources.get();; if (map == null); { return null; } Object value = map.get(key);; return value; } public static void bindResource(Object key, Object value); throws IllegalStateException { Map map = (Map); resources.get();; if (map == null); { map = new HashMap();; resources.set(map);; } map.put(key, value);; }
原来TransactionSynchronizationManager内部建立了一个ThreadLocal的resources,这个resources又是和一个map联系在一起的,这个map在某个线程第一次调用bindResource时生成。
联系前面的DataSourceUtils代码,我们可以总结出来。
某个线程使用DataSourceUtils,当第一次要求创建连接将在TransactionSynchronizationManager中创建出一个ThreadLocal的map。然后以DataSource作为键,ConnectionHolder为值放到map中。等这个线程下一次再请求的这个DataSource的时候,就从这个map中获取对应的ConnectionHolder。用map是为了解决同一个线程上多个DataSource。
然后我们来看看ConnectionHolder又是什么?
3 对连接进行引用计数
看ConnectionHolder代码,这个类很简单,看不出个所以然,只好再去看父类代码ResourceHolderSupport,我们感兴趣的是这两个方法
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
public void requested(); {
this.referenceCount++;
}
public void released(); {
this.referenceCount--;
}
public void requested(); { this.referenceCount++; } public void released(); { this.referenceCount--; }
看得出这是一个引用计数的技巧。原来Spring中对Connection是竟量使用已创建的对象,而不是每次都创建一个新对象。这就是DataSourceUtils中
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
if (conHolder != null); {
conHolder.requested();;
return conHolder.getConnection();;
}
if (conHolder != null); { conHolder.requested();; return conHolder.getConnection();; }
的原因
4 释放连接
完成事物后DataSourceTransactionManager有这样的代码
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
protected void doCleanupAfterCompletion(Object transaction); {
DataSourceTransactionObject txObject = (DataSourceTransactionObject); transaction;
// Remove the connection holder from the thread.
TransactionSynchronizationManager.unbindResource(this.dataSource);;
txObject.getConnectionHolder();.clear();;
//... DataSourceUtils.closeConnectionIfNecessary(con, this.dataSource);;
}
protected void doCleanupAfterCompletion(Object transaction); { DataSourceTransactionObject txObject = (DataSourceTransactionObject); transaction; // Remove the connection holder from the thread. TransactionSynchronizationManager.unbindResource(this.dataSource);; txObject.getConnectionHolder();.clear();; //... DataSourceUtils.closeConnectionIfNecessary(con, this.dataSource);; }
DataSourceUtils
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
protected static void doCloseConnectionIfNecessary(Connection con, DataSource dataSource); throws SQLException {
if (con == null); {
return;
}
ConnectionHolder conHolder = (ConnectionHolder); TransactionSynchronizationManager.getResource(dataSource);;
if (conHolder != null && con == conHolder.getConnection();); {
// It's the transactional Connection: Don't close it.
conHolder.released();;
return;
}
// Leave the Connection open only if the DataSource is our
// special data source, and it wants the Connection left open.
if (!(dataSource instanceof SmartDataSource); || ((SmartDataSource); dataSource);.shouldClose(con);); {
logger.debug("Closing JDBC connection");;
con.close();;
}
}
protected static void doCloseConnectionIfNecessary(Connection con, DataSource dataSource); throws SQLException { if (con == null); { return; } ConnectionHolder conHolder = (ConnectionHolder); TransactionSynchronizationManager.getResource(dataSource);; if (conHolder != null && con == conHolder.getConnection();); { // It's the transactional Connection: Don't close it. conHolder.released();; return; } // Leave the Connection open only if the DataSource is our // special data source, and it wants the Connection left open. if (!(dataSource instanceof SmartDataSource); || ((SmartDataSource); dataSource);.shouldClose(con);); { logger.debug("Closing JDBC connection");; con.close();; } }
恍然大悟。如果事物完成,那么就
TransactionSynchronizationManager.unbindResource(this.dataSource);将当前的ConnectionHolder
从TransactionSynchronizationManager上脱离,然后doCloseConnectionIfNecessary。最后会把连接关闭掉。
5 两个辅助类JdbcTemplate和TransactionAwareDataSourceProxy
JdbcTemplate中的execute方法的第一句和最后一句
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
public Object execute(PreparedStatementCreator psc, PreparedStatementCallback action);
throws DataAccessException {
Connection con = DataSourceUtils.getConnection(getDataSource(););;
//其他代码
DataSourceUtils.closeConnectionIfNecessary(con, getDataSource(););;
}
}
public Object execute(PreparedStatementCreator psc, PreparedStatementCallback action); throws DataAccessException { Connection con = DataSourceUtils.getConnection(getDataSource(););; //其他代码 DataSourceUtils.closeConnectionIfNecessary(con, getDataSource(););; } }
作用不言自明了吧
从TransactionAwareDataSourceProxy中获取的连接是这个样子的
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
public Connection getConnection(); throws SQLException {
Connection con = DataSourceUtils.doGetConnection(getTargetDataSource();, true);;
return getTransactionAwareConnectionProxy(con, getTargetDataSource(););;
}
public Connection getConnection(); throws SQLException { Connection con = DataSourceUtils.doGetConnection(getTargetDataSource();, true);; return getTransactionAwareConnectionProxy(con, getTargetDataSource(););; }
万变不离其宗,不过我们还是看看getTransactionAwareConnectionProxy
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
protected Connection getTransactionAwareConnectionProxy(Connection target, DataSource dataSource); {
return (Connection); Proxy.newProxyInstance(
ConnectionProxy.class.getClassLoader();,
new Class[] {ConnectionProxy.class},
new TransactionAwareInvocationHandler(target, dataSource););;
}
protected Connection getTransactionAwareConnectionProxy(Connection target, DataSource dataSource); { return (Connection); Proxy.newProxyInstance( ConnectionProxy.class.getClassLoader();, new Class[] {ConnectionProxy.class}, new TransactionAwareInvocationHandler(target, dataSource););; }
原来返回的是jdk的动态代理。继续看TransactionAwareInvocationHandler
Java代码
![](https://oscdn.geek-share.com/Uploads/Images/Content/201706/d7d454600f77758df47d870acbf00b9c.gif)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201212/7a1e7afc0f2addbbdb746966b60e9e4a.png)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201304/ffb34937a6f01b9d5cc633a2ffcdf885.gif)
public Object invoke(Object proxy, Method method, Object[] args); throws Throwable {
//... if (method.getName();.equals(CONNECTION_CLOSE_METHOD_NAME);); {
if (this.dataSource != null); {
DataSourceUtils.doCloseConnectionIfNecessary(this.target, this.dataSource);;
}
return null;
}
}
public Object invoke(Object proxy, Method method, Object[] args); throws Throwable { //... if (method.getName();.equals(CONNECTION_CLOSE_METHOD_NAME);); { if (this.dataSource != null); { DataSourceUtils.doCloseConnectionIfNecessary(this.target, this.dataSource);; } return null; } }
TransactionAwareDataSourceProxy会先从DataSourceUtils获取连接。然后将这个连接用jdk的动态代理包一下返回。外部代码如果调用的这个冒牌的Connection,就会先调用TransactionAwareInvocationHandler的invoke,在这个invoke 中,完成原来调用DataSourceUtils的功能。
总结上面的流程
Spring 对DataSource进行事务管理的关键在于ConnectionHolder和TransactionSynchronizationManager。
0.先从TransactionSynchronizationManager中尝试获取连接
1.如果前一步失败则在每个线程上,对每个DataSouce只创建一个Connection
2.这个Connection用ConnectionHolder包装起来,由TransactionSynchronizationManager管理
3.再次请求同一个连接的时候,从TransactionSynchronizationManager返回已经创建的ConnectionHolder,然后调用ConnectionHolder的request将引用计数+1
4.释放连接时要调用ConnectionHolder的released,将引用计数-1
5.当事物完成后,将ConnectionHolder从TransactionSynchronizationManager中解除。当谁都不用,这个连接被close
以上所有都是可以调用DataSourceUtils化简代码,而JdbcTemplate又是调用DataSourceUtils的。所以在Spring文档中要求尽量首先使用JdbcTemplate,其次是用DataSourceUtils来获取和释放连接。至于TransactionAwareDataSourceProxy,那是下策的下策。不过可以将Spring事务管理和遗留代码无缝集成。
所以如某位朋友说要使用Spring的事务管理,但是又不想用JdbcTemplate,那么可以考虑TransactionAwareDataSourceProxy。这个类是原来DataSource的代理。
其次,想使用Spring事物,又不想对Spring进行依赖是不可能的。与其试图自己模拟DataSourceUtils,不如直接使用现成的。
相关文章推荐
- spring源码分析之spring-jdbc模块详解
- spring源码分析之spring-jdbc模块详解
- spring源码分析-web容器初始化过程解析1
- Spring集成Spring-data-redis RedisCacheManager缓存源码分析
- 分析spring源码第一篇:DefaultListableBeanFactory
- 做一个合格的程序猿之浅析Spring AOP源码(十六) 分析ProxyFactory
- Spring 源码分析(三) —— AOP(四)获取指定增强
- Dorado 7 源码分析(一)SpringContextLoaderListener
- spring源码分析,重新认识spring六(从new FileSystemXmlApplicationContext 开始解读)
- 【Spring源码分析】AOP源码解析(下篇)
- Dubbo源码分析(三):自定义Schema--基于Spring可扩展Schema提供自定义配置支持(spring配置文件中 配置标签支持)
- 分析spring源码第五(三)篇:Spring中Bean的解析、加载、创建 过程总结
- 【Spring源码分析】非懒加载的单例Bean初始化过程(上篇)
- Spring对注解(Annotation)处理源码分析2——解析和注入注解配置的资源
- Spring Boot + Spring Security 防止用户在多处同时登录(一个用户同时只能登录一次)及源码分析
- spring Quartz 源码分析--触发器类CronTriggerBean源码剖析
- springmvc工作原理以及源码分析(基于spring3.1.0)
- spring cloud zuul网关服务重试请求配置和源码分析
- Spring源码分析——JdbcTemplate执行批量insert操作