- 浏览: 271587 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
JQ_AK47:
利用中午午休的时间看完了。这个Maven序列。在今天2017- ...
Maven实战(七)settings.xml相关配置 -
gongchuangsu:
赞,总结的真不错
Maven实战(六)依赖 -
无心呢喃:
现在最新的eclipse已经自带maven
Maven实战(三)Eclipse构建Maven项目 -
海云台119:
分析不错,最后的例子也充分说明“要保持响应流和编码和浏览器解 ...
JAVA编码(中文转码)问题总结 -
shengshihouzhe:
scope的import类型没有讲到
Maven实战(六)依赖
事务控制流程
例如对如下代码进行事务控制
class service1{ method1(){ method2(); } }
class service2{ method2(); }
原理:建立一个method interceptor 拦截service的方法,在方法开始前begin事务,方法结束后commit事务
对于上述例子的流程为:
1. method1 begin transaction,新建一个事务并将该事务存储到当前线程当中,建立一个对象transInfo,存储方法id和transaction引用,并标记status为new
2. method1 proceed(出现异常回滚事务)
3. method2 begin transaction,判断当前线程是否有事务,如果有则使用当前事务,建立一个对象transInfo,标记status为exist
4. method2 proceed(出现异常回滚事务)
5. method2 commit 判断transInfo 状态是否为new,否则跳过提交
6. method1 commit 因为状态是new,所以提交
事务执行流程图如下:
1. 初始化事务配置信息TransactionProxyFactoryBean
package org.springframework.transaction.interceptor; import java.util.Properties; import org.springframework.aop.Pointcut; import org.springframework.aop.framework.AbstractSingletonProxyFactoryBean; import org.springframework.aop.support.DefaultPointcutAdvisor; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.transaction.PlatformTransactionManager; public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean implements BeanFactoryAware { private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor(); private Pointcut pointcut; public void setTransactionManager(PlatformTransactionManager transactionManager) { this.transactionInterceptor.setTransactionManager(transactionManager); } public void setTransactionAttributes(Properties transactionAttributes) { this.transactionInterceptor.setTransactionAttributes(transactionAttributes); } public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) { this.transactionInterceptor.setTransactionAttributeSource(transactionAttributeSource); } public void setPointcut(Pointcut pointcut) { this.pointcut = pointcut; } public void setBeanFactory(BeanFactory beanFactory) { this.transactionInterceptor.setBeanFactory(beanFactory); } @Override protected Object createMainInterceptor() { this.transactionInterceptor.afterPropertiesSet(); if (this.pointcut != null) { return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor); } else { // Rely on default pointcut. return new TransactionAttributeSourceAdvisor(this.transactionInterceptor); } } }
2.TransactionInterceptor 事务拦截器
package org.springframework.transaction.interceptor; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Properties; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.BeanFactory; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager; import org.springframework.transaction.support.TransactionCallback; @SuppressWarnings("serial") public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { //拦截methods进行事务处理,每个advisor都会进行一次拦截 public Object invoke(final MethodInvocation invocation) throws Throwable { // Work out the target class: may be <code>null</code>. // 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); // If the transaction attribute is null, the method is non-transactional. final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass); //获取TransactionManager,一般情况下为配置文件配置好的TranstionManager final PlatformTransactionManager tm = determineTransactionManager(txAttr); final String joinpointIdentification = methodIdentification(invocation.getMethod(), targetClass); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. //开始一个事务,将事务信息封装到TransactionInfo 并绑定到当前线程 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.proceed(); } catch (Throwable ex) { // target invocation exception //出现异常时对事务做相应处理 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } //提交事务 commitTransactionAfterReturning(txInfo); return retVal; } else { // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in. try { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, new TransactionCallback<Object>() { public Object doInTransaction(TransactionStatus status) { TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); try { return invocation.proceed(); } catch (Throwable ex) { if (txAttr.rollbackOn(ex)) { // A RuntimeException: will lead to a rollback. if (ex instanceof RuntimeException) { throw (RuntimeException) ex; } else { throw new ThrowableHolderException(ex); } } else { // A normal return value: will lead to a commit. return new ThrowableHolder(ex); } } finally { cleanupTransactionInfo(txInfo); } } }); // Check result: It might indicate a Throwable to rethrow. if (result instanceof ThrowableHolder) { throw ((ThrowableHolder) result).getThrowable(); } else { return result; } } catch (ThrowableHolderException ex) { throw ex.getCause(); } } } }
2.1事务开启相关源代码研究
TransactionInterceptor invoke方法中
//开始一个事务,并将事务信息封装到TransactionInfo TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
跟进该方法源代码:
Class TransactionAspectSupport
protected TransactionInfo createTransactionIfNecessary( PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) { // If no name specified, apply method identification as transaction name. if (txAttr != null && txAttr.getName() == null) { txAttr = new DelegatingTransactionAttribute(txAttr) { @Override public String getName() { return joinpointIdentification; } }; } TransactionStatus status = null; if (txAttr != null) { if (tm != null) { //如果当前线程中没有事务,则开启一个事务,若事务已经存在,则使用该事务 status = tm.getTransaction(txAttr); } else { if (logger.isDebugEnabled()) { logger.debug("Skipping transactional joinpoint [" + joinpointIdentification + "] because no transaction manager has been configured"); } } } return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }
createTransactionIfNecessary方法中
//如果当前线程中没有事务,则开启一个事务,若事务已经存在,则使用该事务 status = tm.getTransaction(txAttr);
跟进该方法源代码:
ClassAbstractPlatformTransactionManager
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { Object transaction = doGetTransaction();//调用具体的TransactionManager实现类获取Transaction // Cache debug flag to avoid repeated checks. boolean debugEnabled = logger.isDebugEnabled(); if (definition == null) { // Use defaults if no transaction definition given. definition = new DefaultTransactionDefinition(); } if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. return handleExistingTransaction(definition, transaction, debugEnabled); } // Check definition settings for new transaction. if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } // No existing transaction found -> check propagation behavior to find out how to proceed. if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { SuspendedResourcesHolder suspendedResources = suspend(null); if (debugEnabled) { logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition); } try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //调用具体TransactionManager开启事务的方法 doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } catch (RuntimeException ex) { resume(null, suspendedResources); throw ex; } catch (Error err) { resume(null, suspendedResources); throw err; } } else { // Create "empty" transaction: no actual transaction, but potentially synchronization. boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } }
getTransaction方法中
//调用具体TransactionManager开启事务的方法 doBegin(transaction, definition);
跟进其源代码:
ClassHibernateTransactionManager
@Override protected void doBegin(Object transaction, TransactionDefinition definition) { HibernateTransactionObject txObject = (HibernateTransactionObject) transaction; if (txObject.hasConnectionHolder() && !txObject.getConnectionHolder().isSynchronizedWithTransaction()) { throw new IllegalTransactionStateException( "Pre-bound JDBC Connection found! HibernateTransactionManager does not support " + "running within DataSourceTransactionManager if told to manage the DataSource itself. " + "It is recommended to use a single HibernateTransactionManager for all transactions " + "on a single DataSource, no matter whether Hibernate or JDBC access."); } Session session = null; try { if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) { Interceptor entityInterceptor = getEntityInterceptor(); Session newSession = (entityInterceptor != null ? getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession()); if (logger.isDebugEnabled()) { logger.debug("Opened new Session [" + SessionFactoryUtils.toString(newSession) + "] for Hibernate transaction"); } txObject.setSession(newSession); } session = txObject.getSessionHolder().getSession(); if (this.prepareConnection && isSameConnectionForEntireSession(session)) { // We're allowed to change the transaction settings of the JDBC Connection. if (logger.isDebugEnabled()) { logger.debug( "Preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]"); } Connection con = session.connection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); } else { // Not allowed to change the transaction settings of the JDBC Connection. if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { // We should set a specific isolation level but are not allowed to... throw new InvalidIsolationLevelException( "HibernateTransactionManager is not allowed to support custom isolation levels: " + "make sure that its 'prepareConnection' flag is on (the default) and that the " + "Hibernate connection release mode is set to 'on_close' (SpringTransactionFactory's default). " + "Make sure that your LocalSessionFactoryBean actually uses SpringTransactionFactory: Your " + "Hibernate properties should *not* include a 'hibernate.transaction.factory_class' property!"); } if (logger.isDebugEnabled()) { logger.debug( "Not preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]"); } } if (definition.isReadOnly() && txObject.isNewSession()) { // Just set to NEVER in case of a new Session for this transaction. session.setFlushMode(FlushMode.MANUAL); } if (!definition.isReadOnly() && !txObject.isNewSession()) { // We need AUTO or COMMIT for a non-read-only transaction. FlushMode flushMode = session.getFlushMode(); if (flushMode.lessThan(FlushMode.COMMIT)) { session.setFlushMode(FlushMode.AUTO); txObject.getSessionHolder().setPreviousFlushMode(flushMode); } } Transaction hibTx; // Register transaction timeout. int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { // Use Hibernate's own transaction timeout mechanism on Hibernate 3.1+ // Applies to all statements, also to inserts, updates and deletes! hibTx = session.getTransaction(); hibTx.setTimeout(timeout); hibTx.begin(); } else { // Open a plain Hibernate transaction without specified timeout. hibTx = session.beginTransaction(); } // Add the Hibernate transaction to the session holder. txObject.getSessionHolder().setTransaction(hibTx); // Register the Hibernate Session's JDBC Connection for the DataSource, if set. if (getDataSource() != null) { Connection con = session.connection(); ConnectionHolder conHolder = new ConnectionHolder(con); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { conHolder.setTimeoutInSeconds(timeout); } if (logger.isDebugEnabled()) { logger.debug("Exposing Hibernate transaction as JDBC transaction [" + con + "]"); } TransactionSynchronizationManager.bindResource(getDataSource(), conHolder); txObject.setConnectionHolder(conHolder); } // Bind the session holder to the thread. if (txObject.isNewSessionHolder()) { TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder()); } txObject.getSessionHolder().setSynchronizedWithTransaction(true); } catch (Exception ex) { if (txObject.isNewSession()) { try { if (session.getTransaction().isActive()) { session.getTransaction().rollback(); } } catch (Throwable ex2) { logger.debug("Could not rollback Session after failed transaction begin", ex); } finally { SessionFactoryUtils.closeSession(session); } } throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex); } }
相关推荐
在整个源代码分析中,我们可以看到 Spring 实现声明式事务管理有三个部分: 1. 对在上下文中配置的属性的处理,这里涉及的类是 TransactionAttributeSourceAdvisor,这是一个通知器,用它来对属性值进行处理,属性...
Spring源代码解析(六):Spring声明式事务处理 Spring源代码解析(七):Spring AOP中对拦截器调用的实现 Spring源代码解析(八):Spring驱动Hibernate的实现 Spring源代码解析(九):Spring Acegi框架鉴权的实现 ...
Spring源代码解析6:Spring声明式事务处理 .doc Spring源代码解析7:Spring AOP中对拦截器调用的实现 .doc Spring源代码解析8:Spring驱动Hibernate的实现.doc Spring源代码解析9:Spring Acegi框架鉴权的实现.doc ...
Spring源代码解析6:Spring声明式事务处理 ; Spring源代码解析7:Spring AOP中对拦截器调用的实现 Spring源代码解析8:Spring驱动Hibernate的实现;Spring源代码解析9:Spring Acegi框架鉴权的实现 Spring源...
总的来说,Spring 3和Hibernate 4结合使用声明式事务管理,使得我们无需在代码中显式调用事务开始、提交和回滚,而是通过注解和配置文件来声明事务的边界和行为。这种方式降低了代码的复杂度,提高了可维护性和可...
Spring框架的声明式事务处理是其企业级应用中的核心特性之一,它允许开发者通过配置来管理事务,而无需在代码中显式地控制事务的开始、提交和回滚。这种方式极大地提高了代码的可读性和可维护性。在这个"spring声明...
在Spring框架中,声明式事务管理是实现事务处理的一种高效且灵活的方式,它允许开发者通过XML配置或注解来定义事务边界,而无需在业务逻辑代码中显式地调用开始、提交或回滚事务的方法。这篇博文"Spring使用XML配置...
总之,Spring的声明式事务管理简化了事务处理,降低了代码的复杂性,而Hibernate的编程式事务管理则提供了更多的控制。在实际项目中,根据需求选择适合的事务管理方式,Spring和Hibernate的集成则为Java开发提供了...
Spring与MyBatis的整合,一方面利用Spring管理MyBatis的SqlSessionFactory和SqlSession,另一方面Spring通过AOP提供声明式事务管理,进一步简化了数据库操作代码。在声明式事务管理中,我们可以在业务逻辑方法上添加...
5. **事务管理**:"spring源代码解析(六):spring声明式事物处理.doc"分析了Spring如何提供声明式事务管理,包括@Transactional注解的工作原理和事务传播行为。 6. **Spring与Hibernate集成**:"spring源代码解析...
在IT行业中,事务处理是确保数据一致性与完整性的关键机制,尤其是在...通过学习和实践这些源代码,开发者可以更好地理解和掌握Spring中的声明式事务处理机制,并将其应用于实际项目中,提升应用的稳定性和可靠性。
它提供了声明式事务管理,使得事务处理更加简单。例如,`@Transactional`注解可以方便地进行事务控制。 6. **Spring Boot**: Spring Boot简化了Spring应用程序的启动和配置,通过自动配置和起步依赖,让开发者...
**声明式事务管理** 是Spring提供的事务管理方式之一,主要通过AOP实现。在Spring中,可以使用`@Transactional`注解在方法级别声明事务边界。当该方法执行时,Spring会自动处理事务的开启、提交或回滚,这极大地简化...
Spring 提供了声明式事务管理,允许开发者在不编写事务管理代码的情况下实现事务控制,极大地简化了事务处理。 实验环境主要包括 Eclipse 或 MyEclipse 开发工具,以及 Spring 4.0 及以上版本,JDK 1.7 及以上版本...
通过这些步骤,我们可以将业务逻辑与数据访问层分离,同时借助Spring的声明式事务管理,提高代码的可读性和维护性。 总的来说,Spring 2.5整合iBATIS 2.3是一个常见的Java应用架构模式,它允许我们在不牺牲灵活性和...
6. **面向切面的事务管理**:Spring3.0提供了声明式事务管理,使得开发者无需在代码中显式处理事务边界。`org.springframework.transaction`包包含了事务管理的相关API。 7. **测试支持**:Spring提供了方便的测试...
在"声明式事务控制,spring2.5+hibernate3集成源码"中,开发者可以学习如何配置Spring的事务管理器,以及如何在Hibernate的SessionFactory和SessionFactoryBuilder上使用Spring的TransactionProxyFactoryBean来创建...