Spring 事务简要说明

/**
对于 <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;
}
 

猜你喜欢

转载自java12345678.iteye.com/blog/2373322
今日推荐