`
liking_csdn
  • 浏览: 2383 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

struts2 spring3 hibernate3 OpenSessionInView+声明式声明的源代码执行过程分析

阅读更多
本文主要对SSh2+OpenSessionInView和Spring声明式的事务,用最常见的配置做一些源代码的分析。第一次发帖,有错的地方,请指教

首先我们贴出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();
	}
分享到:
评论
1 楼 Jnerd 2013-08-16  
写得好多,可是我还是不明白,为什么我的open session in view没效果

相关推荐

    struts-2.3.24.1+spring4.2.1+hibernate5.0

    6. **整合 Spring 和 Hibernate**:配置数据源,创建 SessionFactory,通过 Spring 的 HibernateTemplate 或者 SessionFactory 的 OpenSessionInView 模式进行数据访问。 7. **测试与调试**:确保所有组件能够正常...

    struts2+hirbate+spring面试题

    Struts2、Spring和Hibernate(SSH)是Java企业级开发中的三大主流框架,它们共同构建了一个强大的MVC(模型-视图-控制器)架构。在面试中,掌握这些框架的基本概念、工作原理以及最佳实践至关重要,尤其是对于刚踏入...

    SSH整合笔记

    在企业级应用开发中,Spring、Struts2 和 Hibernate 组合起来被广泛称为 SSH 框架。这些框架各自解决了不同的问题,但组合在一起可以提供一个非常强大的解决方案。下面将详细介绍三大框架如何整合。 **1. 整合思路*...

    Spring的学习笔记

    - **事务管理**:Spring支持声明式和编程式事务管理,包括@Transactional注解和XML配置。 **SSH整合** - **Struts2,Hibernate,Spring**:SSH是Java企业级开发的常用组合,涉及各框架的jar包集成,配置文件调整,...

    Spring框架1

    1. **Spring AOP(面向切面编程)**:Spring AOP 是一种用于实现横切关注点(如日志、事务管理)的技术,它允许我们在不修改源代码的情况下,向应用程序中添加额外的功能。Spring AOP 采用动态代理织入切面,分为两...

    SSH面试题

    - **面向切面编程(AOP)**: 在不修改源代码的情况下,向程序中添加新的功能或行为的技术。例如,可以在不修改原有代码的情况下,添加日志记录、权限检查等功能。 - **Spring中的AOP实现**: 通过Spring的AOP模块,...

    ssha 最新 最完整 配置信息

    本文档旨在提供一套详细的配置指南,用于整合Struts1.x、Spring2.x、Hibernate3.x以及DWR2.x等技术栈。通过本指南,开发者可以更好地理解如何将这些框架有效结合,以构建稳定、高效的Java Web应用。 #### 文档约定 ...

    百度面试题汇总(java)

    19. **Hibernate与iBatis的区别**:Hibernate是一种全栈式的ORM框架,而iBatis更偏向于SQL映射框架。 20. **SQL优化技巧**:包括合理使用索引、避免使用SELECT *、减少嵌套查询等。 #### 二、项目经验 1. **描述...

    java面试题-解密版

    - **AOP(Aspect Oriented Programming)**:面向切面编程,通过代理模式实现在不修改源代码的情况下添加功能。 #### 9. Hibernate的懒加载机制与OpenSessionInView原理 - **懒加载**:只在真正需要时才加载关联...

Global site tag (gtag.js) - Google Analytics