/** 对于 <tx:annotation-driven transaction-manager="txManager" /> 配置的事务(在方法上标注@Transaction) 或 使用AOP配置的事件: <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" /> <tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/> </tx:attributes> </tx:advice> <aop:config> <aop:advisor pointcut="execution(* *..*Service*.*(..))" advice-ref="txAdvice" /> </aop:config> spring 能过AOP方式(CGLIB) 在切面(需要启用事务的方法被调用时)上调用TransactionInterceptor。 TransactionInterceptor 实现了方法拦截器: implements org.aopalliance.intercept.MethodInterceptor 示意逻辑: TransactionStatus transactionStatus = platformTransactionManager.getTransaction(); try{ //这里调用业务逻辑 }catch(Throwable ex){ platformTransactionManager.rollback(transactionStatus); throw ex; } platformTransactionManager.commit(transactionStatus); platformTransactionManager的子类 DataSourceTransactionManager 在启用事务时,从当前线程获取ConnectionHolder,如果不存在则创建一个,并绑定定到线程中。 (从线程中获取ConnectionHolder :TransactionSynchronizationManager.getResource(this.dataSource) 绑定ConnectionHolder到线程的对象为:TransactionSynchronizationManager.bindResource(this.dataSource,ConnectionHolder) ) ConnectionHolder保存在TransactionStatus中(实际子类为:DefaultTransactionStatus),以便commit或rollback可以拿到同一个Connection。 在执行sql里,如JdbcTemplate 是如何拿到同一个Connection的? Connection con = DataSourceUtils.getConnection(getDataSource()); DataSourceUtils会从当前线程中获到ConnectionHolder,如果存在直接获取使用, 如果不存在,则从DataSource中获取一个Connection, 判断是否有事务(TransactionSynchronizationManager.isSynchronizationActive()), 如果有则创建ConnectionHolder并存入当线程线(TransactionSynchronizationManager.bindResource(dataSource, ConnectionHolder);)以备下次用 如果没有,则直接返回Connnection.(无事务时每次用到Connection都会新建一个) 说明:当启用事务时,获取了 Connection(ConnctionHolder),就与当前线程绑定,JdbcTemplate 每次操作可以取得线程内的同一个Connection操作。 **/ /** 相关代码 : TransactionInterceptor方法: **/ @Override public Object invoke(final MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport's invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() { @Override public Object proceedWithInvocation() throws Throwable { return invocation.proceed();//实际的业务逻辑 } }); } /** * * */ protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // If the transaction attribute is null, the method is non-transactional. final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); final PlatformTransactionManager tm = determineTransactionManager(txAttr); final String joinpointIdentification = methodIdentification(method, targetClass); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {//不是CallbackPreferringPlatformTransactionManager // Standard transaction demarcation with getTransaction and commit/rollback calls. //启用事务--调用PlatformTransactionManager(实际子类如DataSourceTransactionManager )的getTransaction方法启用事务 //创建TransactionInfo(内部持有PlatformTransactionManager) 并绑定到当前线程 TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. retVal = invocation.proceedWithInvocation();调用实际的业务逻辑 } catch (Throwable ex) { // target invocation exception //异常rollback //txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo);//清除信息 } //提交事务 //txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); commitTransactionAfterReturning(txInfo);//提交数据库 return retVal; } else { // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in. //如果是CallbackPreferringPlatformTransactionManager。。。。 //忽略部分代码 } } DataSourceTransactionManager是PlatformTransactionManager的子类,提供了事务处理能力。 public class DataSourceTransactionManager extends AbstractPlatformTransactionManager{ private DataSource dataSource;//内部持有数据源对象 /** * * */ protected Object doGetTransaction() { DataSourceTransactionObject txObject = new DataSourceTransactionObject();//创建DataSourceTransactionObject对象它持有ConnectionHolder txObject.setSavepointAllowed(isNestedTransactionAllowed()); ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);//当前线程中获取 txObject.setConnectionHolder(conHolder, false); return txObject; } @Override protected void doBegin(Object transaction, TransactionDefinition definition) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; Connection con = null; try { if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { Connection newCon = this.dataSource.getConnection(); if (logger.isDebugEnabled()) { logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); } txObject.setConnectionHolder(new ConnectionHolder(newCon), true);//获取Connection存入 ConnectionHolder 对象,内部持有Connection, } txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); // Switch to manual commit if necessary. This is very expensive in some JDBC drivers, // so we don't want to do it unnecessarily (for example if we've explicitly // configured the connection pool to set it already). if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true); if (logger.isDebugEnabled()) { logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); } con.setAutoCommit(false);//设置自动提交为false } txObject.getConnectionHolder().setTransactionActive(true);//标记事务启动状态 // Bind the session holder to the thread. if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());//绑定ConnectionHolder到当前线程 } } catch (Throwable ex) { if (txObject.isNewConnectionHolder()) { DataSourceUtils.releaseConnection(con, this.dataSource); txObject.setConnectionHolder(null, false); } throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); } } //启用事务,内部调用 public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { //非实际代码,忽略了部分代码 Object transaction = doGetTransaction(); try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus(//创建TransactionStatus对象内部持有DataSourceTransactionObject definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } } /** * * DefaultTransactionStatus--持有-->DataSourceTransactionObject--持有-->ConnectionHolder--持有-》Connection-->commit() */ protected void doCommit(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); try { con.commit();//提交 } catch (SQLException ex) { throw new TransactionSystemException("Could not commit JDBC transaction", ex); } } /** * * DefaultTransactionStatus--持有-->DataSourceTransactionObject--持有-->ConnectionHolder--持有-》Connection-->rollback() */ protected void doRollback(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); try { con.rollback();//事务回滚 } catch (SQLException ex) { throw new TransactionSystemException("Could not roll back JDBC transaction", ex); } } JdbcTemplate 通过 DataSourceUtils 获得Connction: public static Connection doGetConnection(DataSource dataSource) throws SQLException { Assert.notNull(dataSource, "No DataSource specified"); ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);//当线 if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) { conHolder.requested(); if (!conHolder.hasConnection()) { logger.debug("Fetching resumed JDBC Connection from DataSource"); conHolder.setConnection(dataSource.getConnection()); } return conHolder.getConnection(); } // Else we either got no holder or an empty thread-bound holder here. logger.debug("Fetching JDBC Connection from DataSource"); Connection con = dataSource.getConnection(); if (TransactionSynchronizationManager.isSynchronizationActive()) { logger.debug("Registering transaction synchronization for JDBC Connection"); // Use same Connection for further JDBC actions within the transaction. // Thread-bound object will get removed by synchronization at transaction completion. ConnectionHolder holderToUse = conHolder; if (holderToUse == null) { holderToUse = new ConnectionHolder(con); } else { holderToUse.setConnection(con); } holderToUse.requested(); TransactionSynchronizationManager.registerSynchronization( new ConnectionSynchronization(holderToUse, dataSource)); holderToUse.setSynchronizedWithTransaction(true); if (holderToUse != conHolder) { TransactionSynchronizationManager.bindResource(dataSource, holderToUse); } } return con; }
Spring 事务简要说明
猜你喜欢
转载自java12345678.iteye.com/blog/2373322
今日推荐
周排行