struts2 spring3 hibernate3 OpenSessionInView+声明式声明的源代码执行过程分析 OpenSessionInView声明式事务sshsession管理spring事务
程序员文章站
2022-05-21 09:32:19
...
本文主要对SSh2+OpenSessionInView和Spring声明式的事务,用最常见的配置做一些源代码的分析。第一次发帖,有错的地方,请指教
首先我们贴出Web.xml的配置。
Spring声明式事务的配置。
贴上OpenSessionInView的源码
OpenSessionInView#getSession(sessionFactory)源码
SessionFactoryUtils.doGetSession()获取Session最核心的一个源码
接下来就是执行对应的Action
生产的代理类看不见源码,直接从JdkDynamicAopProxy类来。。
JdkDynamicAopProxy#invoke 源码
ReflectiveMethodInvocation#proceed 源码
按照我们的配置只有两个拦截器。1是ExposeInvocationInterceptor 2是事务拦截器TransactionInterceptor。ExposeInvocationInterceptor拦截器只是比较简单,只是拦截器放入ThreadLocal中。我们继续讨论最核心的事务拦截器
TransactionInterceptor#invoke 源代码
TransactionAspectSupport#createTransactionIfNecessary() 源代码
AbstractPlatformTransactionManager#getTransaction() 源代码
HibernateTransactionManager#doGetTransaction() 源代码
HibernateTransactionManager#doBegin() 源代码
AbstractPlatformTransactionManager#prepareSynchronization 源代码
下面是 提交事务的代码分析
AbstractPlatformTransactionManager#commit
AbstractPlatformTransactionManager#processCommit() 源代码
AbstractPlatformTransactionManager#cleanupAfterCompletion 源代码
HibernateTransactionManger#doCleanupAfterCompletion 源代码
首先我们贴出Web.xml的配置。
<filter> <filter-name>hibernateFilter</filter-name> <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>singleSession</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Spring声明式事务的配置。
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <tx:advice id="advice" transaction-manager="txManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="del*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="find*" read-only="true" /> <tx:method name="save*" propagation="REQUIRED" /> </tx:attributes> </tx:advice> <aop:config proxy-target-class="false"> <aop:pointcut expression="execution(* cn.service.impl.*.*(..))" id="pointcut" /> <aop:advisor advice-ref="advice" pointcut-ref="pointcut" /> </aop:config>
贴上OpenSessionInView的源码
protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { //获取SessionFactory,就是WebApplicationContext.getBean(getSessionFactoryBeanName(), SessionFactory.class); SessionFactory sessionFactory = lookupSessionFactory(request); boolean participate = false; //是否是单Session模式 if (isSingleSession()) { // 看看当前线程是否有绑定的资源。一般请求过来是没有的 if (TransactionSynchronizationManager.hasResource(sessionFactory)) { // Do not modify the Session: just set the participate flag. participate = true; } else { //打开一个Session,在下面会讲到如何获取的Session的 logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter"); Session session = getSession(sessionFactory); //把获取的Session绑定到当前线程中。即ThreadLocal<Map<Object,Object>> //这里Map的key是sessionFactory,value是SessionHolder,而真正的Session又是放在SessionHolder里面的一个同步的Map中。kew是一个默认的Object。value才是真正的Session TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session)); } } else { // 这是延期关闭模式,本文不做讨论 if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) { // Do not modify deferred close: just set the participate flag. participate = true; } else { SessionFactoryUtils.initDeferredClose(sessionFactory); } } try { //放行。。执行action-->service-->dao filterChain.doFilter(request, response); } finally { //如果上文打开了SESSION if (!participate) { //是单session模式 if (isSingleSession()) { // 从当前线程移除资源 SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory); logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter"); //关闭Session closeSession(sessionHolder.getSession(), sessionFactory); } else { // deferred close mode SessionFactoryUtils.processDeferredClose(sessionFactory); } } } }
OpenSessionInView#getSession(sessionFactory)源码
protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException { //使用SessionFactoryUtils获取一个Session。第二参数true,代表允许创建新的Session。下面会详细讲解怎么获取Session //一般这里都是打开一个Session Session session = SessionFactoryUtils.getSession(sessionFactory, true); FlushMode flushMode = getFlushMode(); //将FlushMode模式改成MANUAL值 if (flushMode != null) { session.setFlushMode(flushMode); } return session; }
SessionFactoryUtils.doGetSession()获取Session最核心的一个源码
//这里分两个部分。一是开启了事务。二是没有开启事务。 //或者说是一个请求的第一次调用和第2次以上的调用两种模式 //如果是第一次调用过来的没有事务的时候,则打开一个Session,然后返回出去 //如果是第二次以上调用有事务的时候。则是直接返回一个Session private static Session doGetSession( SessionFactory sessionFactory, Interceptor entityInterceptor, SQLExceptionTranslator jdbcExceptionTranslator, boolean allowCreate) throws HibernateException, IllegalStateException { //如果是有事务的 则是第二次以上调用的 则执行以下if条件 Assert.notNull(sessionFactory, "No SessionFactory specified"); //从当前线程中获取SessionHolder SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); //如果sessionHolder不null。并且有Session if (sessionHolder != null && !sessionHolder.isEmpty()) { // pre-bound Hibernate Session Session session = null; //如果开启了事务 并且 sessionHolder中只有一个Session或没有Session if (TransactionSynchronizationManager.isSynchronizationActive() && sessionHolder.doesNotHoldNonDefaultSession()) { // Spring transaction management is active -> // register pre-bound Session with it for transactional flushing. //从SessionHolder中获取检查后的Session。这里其实是检查session有没关闭 session = sessionHolder.getValidatedSession(); //session不等于空 并且 没有开启事务 if (session != null && !sessionHolder.isSynchronizedWithTransaction()) { logger.debug("Registering Spring transaction synchronization for existing Hibernate Session"); //注册一个SpringSessionSynchronization对象到当前线程 TransactionSynchronizationManager.registerSynchronization( new SpringSessionSynchronization(sessionHolder, sessionFactory, jdbcExceptionTranslator, false)); //设置同步事务开启 sessionHolder.setSynchronizedWithTransaction(true); // Switch to FlushMode.AUTO, as we have to assume a thread-bound Session // with FlushMode.MANUAL, which needs to allow flushing within the transaction. //获取session的提交模式 FlushMode flushMode = session.getFlushMode(); //如果提交模式小于COMMIT 并且当前线程的事务不是只读的 if (flushMode.lessThan(FlushMode.COMMIT) && !TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { //将提交模式设置成AUTO session.setFlushMode(FlushMode.AUTO); //将flushMode设置成旧的提交模式 sessionHolder.setPreviousFlushMode(flushMode); } } } else { // 没有Spring事务管理活动。则是着获取Jta事务。这里不是我们的重点。不谈先 session = getJtaSynchronizedSession(sessionHolder, sessionFactory, jdbcExceptionTranslator); } //返回session if (session != null) { return session; } } // -- 没有事务的时候 一个请求第一次的调用-- //打开Session logger.debug("Opening Hibernate Session"); Session session = (entityInterceptor != null ? sessionFactory.openSession(entityInterceptor) : sessionFactory.openSession()); // Use same Session for further Hibernate actions within the transaction. // 一般这if不会被执行。 //如果当前线程的事务是活动的 if (TransactionSynchronizationManager.isSynchronizationActive()) { // We're within a Spring-managed transaction, possibly from JtaTransactionManager. logger.debug("Registering Spring transaction synchronization for new Hibernate Session"); SessionHolder holderToUse = sessionHolder; //如果当前的SessionHolder是空的 if (holderToUse == null) { //实例化一个SessionHolder holderToUse = new SessionHolder(session); } else { //增加一个Session到SessionHodler中。 holderToUse.addSession(session); } //如果当前线程事务的制度的 if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { //将FluashMode设置MANUAL。 session.setFlushMode(FlushMode.MANUAL); } //注册一个SpringSessionSynchronization对象到当前线程中 TransactionSynchronizationManager.registerSynchronization( new SpringSessionSynchronization(holderToUse, sessionFactory, jdbcExceptionTranslator, true)); //设置线程同步事务开启 holderToUse.setSynchronizedWithTransaction(true); //这里比较是开上面是否实例化了SessionHolder。如果是则将SessionHolder绑定到当前线程中 if (holderToUse != sessionHolder) { TransactionSynchronizationManager.bindResource(sessionFactory, holderToUse); } } else { // No Spring transaction management active -> try JTA transaction synchronization. registerJtaSynchronization(session, sessionFactory, jdbcExceptionTranslator, sessionHolder); } // 如果是不允许创建Session 并且 没有开启事务。则抛出异常。因为没有找到Session又不能创建新的。。 if (!allowCreate && !isSessionTransactional(session, sessionFactory)) { closeSession(session); throw new IllegalStateException("No Hibernate Session bound to thread, " + "and configuration does not allow creation of non-transactional one here"); } return session; }
接下来就是执行对应的Action
public UserAction extends BaseAction{ private User user; //省略getset方法 public String addUser(){ //这里面getUserService()方法就是获得Spring的代理类, //这里使用JDK的动态代理在 <aop:config proxy-target-class="false"> 默认就是false //调用这个类的方法之前要经过AOP拦截。下面我们来分析拦截的过程。 this.getServiceFacade().getUserService().addUser(user); } }
生产的代理类看不见源码,直接从JdkDynamicAopProxy类来。。
JdkDynamicAopProxy#invoke 源码
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { MethodInvocation invocation = null; Object oldProxy = null; boolean setProxyContext = false; //获取目标源的包装对象 targetSource包含目标Service对象 TargetSource targetSource = this.advised.targetSource; Class targetClass = null; Object target = null; try { /如果目标类没有重载equals方法 && 目前正在调用目标类的equals方法,那直接调本类重载方法, //这样就不需要再往下走,不需要再开启事务等等多余的操作以至于浪费性能了,下面的几个IF都是做类似的事 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { // Service invocations on ProxyConfig with the proxy config... return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); } Object retVal = null; //如果可以暴露代理对象,即配置<aop:config expose-proxy="true">这个 //则将代理对象放入AOP上下文中 //这样方便在一个Service方法中。调用另一个有事务的方法时。也能起到配置事务的作用。。 调用:((UserService)AopContext.currentProxy()).deleteUser(); if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. //获取目标对象 target = targetSource.getTarget(); if (target != null) { //获取目标对象的class targetClass = target.getClass(); } // Get the interception chain for this method. //根据方法和目标对象的class属性。获取对应的拦截器。 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. //如果拦截器为空。 if (chain.isEmpty()) { // We can skip creating a MethodInvocation: just invoke the target directly // Note that the final invoker must be an InvokerInterceptor so we know it does // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. 直接执行目标方法 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args); } else { // We need to create a method invocation... //实例化一个专门执行拦截器的对象来执行拦截器 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. //进行递归的拦截 retVal = invocation.proceed(); } // Massage return value if necessary. // 调用的返回结果目标类对象本身,就把它替换成代理类对象 if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } return retVal; } //释放资源操作,其实主要是在Aop上下文清除代理对象 finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy);dProxy); } } }
ReflectiveMethodInvocation#proceed 源码
public Object proceed() throws Throwable { // We start with an index of -1 and increment early. //如果没有拦截器则调用目标方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } //获取拦截器 Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); //拦截器是InterceptorAndDynamicMethodMatcher类型 //Spring事务拦截器TransactionInterceptor是MethodInterceptor实现类 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { // Evaluate dynamic method matcher here: static part will already have // been evaluated and found to match. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // Dynamic matching failed. // Skip this interceptor and invoke the next in the chain. //方法匹配失败,跳过,继续递归 return proceed(); } } else { // It's an interceptor, so we just invoke it: The pointcut will have // been evaluated statically before this object was constructed. // 调用事务拦截器等。。 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
按照我们的配置只有两个拦截器。1是ExposeInvocationInterceptor 2是事务拦截器TransactionInterceptor。ExposeInvocationInterceptor拦截器只是比较简单,只是拦截器放入ThreadLocal中。我们继续讨论最核心的事务拦截器
TransactionInterceptor#invoke 源代码
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 Class targetClass = (invocation.getThis() != null ? invocation.getThis().getClass() : null); // 获取事务定义的属性。例如<tx:method name="add*" propagation="REQUIRED" /> 和数据库隔离级别 final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass); //获取事务管理对象。这里是HibernateTransactionManager final PlatformTransactionManager tm = determineTransactionManager(txAttr); //获取方法的全限定名 final String joinpointIdentification = methodIdentification(invocation.getMethod()); //如果配置了事务 或者 事务管理者不是CallbackPreferringPlatformTransactionManager if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. //获取事务信息对象,然后将它邦定到ThreadLocal中,它包含了事务定义和事务的状态。这个TransactionInfo是TransactionAspectSupport的一个内部类 //createTransactionIfNecessary方法在父类TransactionAspectSupport中定义的。下面会细说 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. //继续递归拦截器。一般到这里都是执行我们的Service方法了 retVal = invocation.proceed(); } catch (Throwable ex) { // target invocation exception completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { //从当前线程中清除事务信息对象 cleanupTransactionInfo(txInfo); } //提交事务,清除ThreadLocal中保存的一些事务资源。 //如果是filter-action-service-dao的话。session不会关闭。只//会关闭connection // 如果是直接从service调起的话。session会在事务提交后关闭。具体怎么关闭下面会详细说 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(); } } }
TransactionAspectSupport#createTransactionIfNecessary() 源代码
protected TransactionInfo createTransactionIfNecessary( PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) { // 如果事务没有名字。则使用方面名做为事务的名字。将txAttr进行包装下 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) { //这里调用事务管理器获得一个事务状态对象,这里会涉及真正的事务处理了。 //getTransaction()是事务模板管理器的方法。 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); }
AbstractPlatformTransactionManager#getTransaction() 源代码
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { //获取一个事务对象。这里调用了HibernateTransactionManager事务管理器的方法获取事务对象 Object transaction = doGetTransaction(); // 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. //检查事务超时时间是否合法。不<-1 if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout()); } //如果事务传播特性配置的是mandatory,当前没有事务存在,抛出异常 if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } //如果事务传播特性为required、required_new或nested 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); //创建事务的调用,具体实现由具体的事务处理器提供 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. //创建空事务,针对supported类型的事务传播特性,激活和当前线程绑定的事务 boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); //准备事务状态 return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } }
HibernateTransactionManager#doGetTransaction() 源代码
protected Object doGetTransaction() { //实例化一个HibernateTransactionObject对象。这个类是HibernateTransactionManager的内部类 HibernateTransactionObject txObject = new HibernateTransactionObject(); //设置是否是内嵌的事务 txObject.setSavepointAllowed(isNestedTransactionAllowed()); //从当前线程中获取SessionHolder。如果是filter-action-service的方式这里能获取到,如果直接 //从service调用则sessionHolder== null SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory()); if (sessionHolder != null) { if (logger.isDebugEnabled()) { logger.debug("Found thread-bound Session [" + SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction"); } //把SessionHolder放入HibernateTransactionObject对象。并且标志此session是旧的session txObject.setSessionHolder(sessionHolder); } //如果当前Hibernate事务处理器有被管理的Hibernate Session else if (this.hibernateManagedSession) { try { //获取当前的Hibernate Session Session session = getSessionFactory().getCurrentSession(); if (logger.isDebugEnabled()) { logger.debug("Found Hibernate-managed Session [" + SessionFactoryUtils.toString(session) + "] for Spring-managed transaction"); } //设置Hibernate事务对象已经存在指定的Session txObject.setExistingSession(session); } catch (HibernateException ex) { throw new DataAccessResourceFailureException( "Could not obtain Hibernate-managed Session for Spring-managed transaction", ex); } } //如果获取到的数据源不为null if (getDataSource() != null) { /将获取到的数据源和当前线程绑定 ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(getDataSource()); txObject.setConnectionHolder(conHolder); } return txObject; }
HibernateTransactionManager#doBegin() 源代码
protected void doBegin(Object transaction, TransactionDefinition definition) { //获取事务对象 HibernateTransactionObject txObject = (HibernateTransactionObject) transaction; //如果事务对象有ConnectionHolder,且事务对象的数据库连接不是事务同步的 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 { //如果事务对象没有SessionHolder 或者SessionHolder中的session是同步事务的。 if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) { //获取Hibernate事务处理器中的实体拦截器 Interceptor entityInterceptor = getEntityInterceptor(); //获取Hibernate Session,如果实体拦截器不为null,则打开指定 //实体拦截器的Session,如果实体拦截器为null,则打开新Session Session newSession = (entityInterceptor != null ? getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession()); if (logger.isDebugEnabled()) { logger.debug("Opened new Session [" + SessionFactoryUtils.toString(newSession) + "] for Hibernate transaction"); } //设置session到事务对象中。并标记次session对象是新的session。 txObject.setSession(newSession); } //获取SessionHolder中已有的Hibernate Session session = txObject.getSessionHolder().getSession(); //允许为JDBC连接改变事务设置 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) + "]"); } //获取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) + "]"); } } //如果事务是只读,且事务对象是新的Hibernate Session if (definition.isReadOnly() && txObject.isNewSession()) { // Just set to NEVER in case of a new Session for this transaction. session.setFlushMode(FlushMode.MANUAL); } //如果事务不是只读的 并且事务对象不是新Hibernate Session if (!definition.isReadOnly() && !txObject.isNewSession()) { // We need AUTO or COMMIT for a non-read-only transaction. 获取flushMode模式 FlushMode flushMode = session.getFlushMode(); //如果flushMode小于COMMIT if (flushMode.lessThan(FlushMode.COMMIT)) { //设置成AUTO session.setFlushMode(FlushMode.AUTO); //设置旧的fulshMode到事务对象中 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+ //获取Hibernate Session事务 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. //将事务设置到事务对象的SessionHolder中。 txObject.getSessionHolder().setTransaction(hibTx); //如果数据源不为null,即设置了数据源 // Register the Hibernate Session's JDBC Connection for the DataSource, if set. if (getDataSource() != null) { //使用Hibernate Session打开数据库连接 Connection con = session.connection(); //创建ConnectionHolder 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 + "]"); } //将ConnectionHolder绑定到当前线程中 TransactionSynchronizationManager.bindResource(getDataSource(), conHolder); //把connectionHolder放入事务对象中 txObject.setConnectionHolder(conHolder); } //如果事务对象是新的sessionHolder。则将它邦到当前线程中。(从Service层调用)在此绑定 if (txObject.isNewSessionHolder()) { TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder()); } //设置同步事务状态开启 txObject.getSessionHolder().setSynchronizedWithTransaction(true); } catch (Exception ex) { if (txObject.isNewSession()) { try { //如果session开启了事务,则进行回滚 if (session.getTransaction().isActive()) { session.getTransaction().rollback(); } } catch (Throwable ex2) { logger.debug("Could not rollback Session after failed transaction begin", ex); } finally { //关闭session SessionFactoryUtils.closeSession(session); } } throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex); } }
AbstractPlatformTransactionManager#prepareSynchronization 源代码
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) { //如果是新同步事务,这些线程同步事务都是在TransactionSynchronizationManager管理 if (status.isNewSynchronization()) { //将当前线程的同步事务激活 TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction()); //设置当线程的数据库隔离状态 TransactionSynchronizationManager.setCurrentTransactionIsolationLevel( (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) ? definition.getIsolationLevel() : null); //设置事务当前线程的只读状态 TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly()); //设置当前事务的名称到ThreadLocal TransactionSynchronizationManager.setCurrentTransactionName(definition.getName()); //初始化当前线程对象集合 -- 这是是new LinkedList<TransactionSynchronization>() TransactionSynchronizationManager.initSynchronization(); } }
下面是 提交事务的代码分析
AbstractPlatformTransactionManager#commit
public final void commit(TransactionStatus status) throws TransactionException { //如果事务已提交。则抛出异常 if (status.isCompleted()) { throw new IllegalTransactionStateException( "Transaction is already completed - do not call commit or rollback more than once per transaction"); } DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; //如果事务执行状态时回滚 if (defStatus.isLocalRollbackOnly()) { if (defStatus.isDebug()) { logger.debug("Transactional code has requested rollback"); } //处理事务回滚 processRollback(defStatus); return; } //如果事务没有被标记为回滚时提交,且事务状态时全局回滚 if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) { if (defStatus.isDebug()) { logger.debug("Global transaction is marked as rollback-only but transactional code requested commit"); } //回滚处理 processRollback(defStatus); // Throw UnexpectedRollbackException only at outermost transaction boundary // or if explicitly asked to. //如果事务状态时新事务,或者在全局回滚时失败 if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) { throw new UnexpectedRollbackException( "Transaction rolled back because it has been marked as rollback-only"); } return; } //处理提交 processCommit(defStatus); }
AbstractPlatformTransactionManager#processCommit() 源代码
private void processCommit(DefaultTransactionStatus status) throws TransactionException { try { boolean beforeCompletionInvoked = false; try { //事务提交的准备工作,这里是HibernateTransactionManager实现 prepareForCommit(status); triggerBeforeCommit(status); triggerBeforeCompletion(status); beforeCompletionInvoked = true; boolean globalRollbackOnly = false; //如果事务状态是新事务,或者全局回滚失败 if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) { globalRollbackOnly = status.isGlobalRollbackOnly(); } //嵌套事务处理 if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Releasing transaction savepoint"); } //释放挂起事务保存点 status.releaseHeldSavepoint(); } //如果当前事务是新事务 else if (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction commit"); } //调用hibernateTrancastionManager的doCommit方法。进行真正的提交事务 //而在方法中只是这样操作:status.getTransaction().getSessionHolder().getTransaction().commit(); doCommit(status); } // Throw UnexpectedRollbackException if we have a global rollback-only // marker but still didn't get a corresponding exception from commit. //如果事务被标记为全局回滚 if (globalRollbackOnly) { throw new UnexpectedRollbackException( "Transaction silently rolled back because it has been marked as rollback-only"); } } //提交过程中产生未预期的回滚异常,则回滚处理 catch (UnexpectedRollbackException ex) { // can only be caused by doCommit triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); throw ex; } //对提交过程中产生的事务异常处理 catch (TransactionException ex) { // can only be caused by doCommit //如果回滚失败,则进行回滚异常处理 if (isRollbackOnCommitFailure()) { doRollbackOnCommitException(status, ex); } else { triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); } throw ex; } //对提交过程中产生的异常处理 catch (RuntimeException ex) { //如果不是在完成前调用的 if (!beforeCompletionInvoked) { //触发完成前的回调方法 triggerBeforeCompletion(status); } //进行回滚异常处理 doRollbackOnCommitException(status, ex); throw ex; } //对提交过程中产生的错误处理 catch (Error err) { if (!beforeCompletionInvoked) { triggerBeforeCompletion(status); } doRollbackOnCommitException(status, err); throw err; } // Trigger afterCommit callbacks, with an exception thrown there // propagated to callers but the transaction still considered as committed. try { /触发提交之后的回调操作 triggerAfterCommit(status); } finally { //提交完成之后清除事务相关状态 triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED); } } finally { //这里会进行清除TransactionSynchronizationManager线程中保存的事务资源信息。 //在这里会根据调用的模式:例如filter-action-service-dao。则会在这里关闭connection,不会关闭session //如果是service-dao 这样的模式,则会这次关闭session cleanupAfterCompletion(status); } }
AbstractPlatformTransactionManager#cleanupAfterCompletion 源代码
private void cleanupAfterCompletion(DefaultTransactionStatus status) { status.setCompleted(); //清除TransactionSynchronizationManager的一些事务信息 if (status.isNewSynchronization()) { TransactionSynchronizationManager.clear(); } //如果是新的事务 if (status.isNewTransaction()) { //调用HibernateTransactionManager的的实现,下面分有代码分析 doCleanupAfterCompletion(status.getTransaction()); } //如果挂起了线程。则进行回复原来的事务到线程中 if (status.getSuspendedResources() != null) { if (status.isDebug()) { logger.debug("Resuming suspended transaction after completion of inner transaction"); } resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources()); } }
HibernateTransactionManger#doCleanupAfterCompletion 源代码
protected void doCleanupAfterCompletion(Object transaction) { HibernateTransactionObject txObject = (HibernateTransactionObject) transaction; // Remove the session holder from the thread. //如果是新的sessionHolder,则在线程中移除绑定 if (txObject.isNewSessionHolder()) { TransactionSynchronizationManager.unbindResource(getSessionFactory()); } // Remove the JDBC connection holder from the thread, if exposed. if (getDataSource() != null) { TransactionSynchronizationManager.unbindResource(getDataSource()); } Session session = txObject.getSessionHolder().getSession(); if (this.prepareConnection && session.isConnected() && isSameConnectionForEntireSession(session)) { // We're running with connection release mode "on_close": We're able to reset // the isolation level and/or read-only flag of the JDBC Connection here. // Else, we need to rely on the connection pool to perform proper cleanup. try { Connection con = session.connection(); DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel()); } catch (HibernateException ex) { logger.debug("Could not access JDBC Connection of Hibernate Session", ex); } } //如果在事务对象中标记的是新的session,则在此被关闭。一般都是Service--dao这样的调用方式 if (txObject.isNewSession()) { if (logger.isDebugEnabled()) { logger.debug("Closing Hibernate Session [" + SessionFactoryUtils.toString(session) + "] after transaction"); } SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory()); }//否从则只关闭connection。。 从filter过来的请求 else { if (logger.isDebugEnabled()) { logger.debug("Not closing pre-bound Hibernate Session [" + SessionFactoryUtils.toString(session) + "] after transaction"); } if (txObject.getSessionHolder().getPreviousFlushMode() != null) { session.setFlushMode(txObject.getSessionHolder().getPreviousFlushMode()); } if (!this.hibernateManagedSession) { session.disconnect(); } } //清除事务对象的属性。。 txObject.getSessionHolder().clear(); }
上一篇: Spring 事务 (二) Spring 声明式事务 配置
下一篇: 手机游戏开发展示