⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transactionaspectsupport.java

📁 spring的源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
		// If the transaction attribute is null, the method is non-transactional.
		final TransactionAttribute sourceAttr =
				this.transactionAttributeSource.getTransactionAttribute(method, targetClass);
		TransactionAttribute txAttr = sourceAttr;

		// If no name specified, apply method identification as transaction name.
		if (txAttr != null && txAttr.getName() == null) {
			final String name = methodIdentification(method);
			txAttr = new DelegatingTransactionAttribute(sourceAttr) {
				public String getName() {
					return name;
				}
			};
		}

		TransactionInfo txInfo = new TransactionInfo(txAttr, method);
		if (txAttr != null) {
			// We need a transaction for this method
			if (logger.isDebugEnabled()) {
				logger.debug("Getting transaction for " + txInfo.joinpointIdentification());
			}

			// The transaction manager will flag an error if an incompatible tx already exists
			txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr));
		}
		else {
			// The TransactionInfo.hasTransaction() method will return
			// false. We created it only to preserve the integrity of
			// the ThreadLocal stack maintained in this class.
			if (logger.isDebugEnabled())
				logger.debug("Don't need to create transaction for [" + methodIdentification(method) +
						"]: this method isn't transactional");
		}

		// We always bind the TransactionInfo to the thread, even if we didn't create
		// a new transaction here. This guarantees that the TransactionInfo stack
		// will be managed correctly even if no transaction was created by this aspect.
		txInfo.bindToThread();
		return txInfo;
	}

	/**
	 * Convenience method to return a String representation of this Method
	 * for use in logging. Can be overridden in subclasses to provide a
	 * different identifier for the given method.
	 * @param method the method we're interested in
	 * @return log message identifying this method
	 * @see org.springframework.util.ClassUtils#getQualifiedMethodName
	 */
	protected String methodIdentification(Method method) {
		return ClassUtils.getQualifiedMethodName(method);
	}

	/**
	 * Execute after successful completion of call, but not
	 * after an exception was handled.
	 * Do nothing if we didn't create a transaction.
	 * @param txInfo information about the current transaction
	 */
	protected void doCommitTransactionAfterReturning(TransactionInfo txInfo) {
		if (txInfo != null && txInfo.hasTransaction()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Invoking commit for transaction on " + txInfo.joinpointIdentification());
			}
			this.transactionManager.commit(txInfo.getTransactionStatus());
		}
	}

	/**
	 * Handle a throwable, closing out the transaction.
	 * We may commit or roll back, depending on our configuration.
	 * @param txInfo information about the current transaction
	 * @param ex throwable encountered
	 */
	protected void doCloseTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
		if (txInfo.hasTransaction()) {
			if (txInfo.transactionAttribute.rollbackOn(ex)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Invoking rollback for transaction on " + txInfo.joinpointIdentification() +
							" due to throwable [" + ex + "]");
				}
				try {
					this.transactionManager.rollback(txInfo.getTransactionStatus());
				}
				catch (RuntimeException ex2) {
					logger.error("Application exception overridden by rollback exception", ex);
					throw ex2;
				}
				catch (Error err) {
					logger.error("Application exception overridden by rollback error", ex);
					throw err;
				}
			}
			else {
				// we don't roll back on this exception
				if (logger.isDebugEnabled()) {
					logger.debug(txInfo.joinpointIdentification() + " threw throwable [" + ex +
							"] but this does not force transaction rollback");
				}
				// will still roll back if TransactionStatus.rollbackOnly is true
				this.transactionManager.commit(txInfo.getTransactionStatus());
			}
		}
	}

	/**
	 * Call this in all cases: exception or normal return. Resets
	 * the TransactionInfo ThreadLocal
	 * @param txInfo information about the current transaction. May be <code>null</code>.
	 */
	protected void doFinally(TransactionInfo txInfo) {
		if (txInfo != null) {
			txInfo.restoreThreadLocalStatus();
		}
	}

	
	//---------------------------------------------------------------------
	// Serialization support
	//---------------------------------------------------------------------
	
	private void readObject(ObjectInputStream ois) throws IOException {
		// Rely on default serialization, just initialize state after deserialization.
		try {
			ois.defaultReadObject();
		}
		catch (ClassNotFoundException ex) {
			throw new AspectException("Failed to deserialize Spring AOP transaction aspect:" +
					"Check that Spring AOP libraries are available on the client side", ex);
		}
		
		// Initialize transient fields
		this.logger = LogFactory.getLog(getClass());
	}


	/**
	 * Opaque object used to hold Transaction information. Subclasses
	 * must pass it back to methods on this class, but not see its internals.
	 */
	protected class TransactionInfo {

		private final TransactionAttribute transactionAttribute;

		// TODO: Could open up to other kinds of joinpoint?
		private final Method method;

		private TransactionStatus transactionStatus;

		private TransactionInfo oldTransactionInfo;

		public TransactionInfo(TransactionAttribute transactionAttribute, Method method) {
			this.transactionAttribute = transactionAttribute;
			this.method = method;
		}

		/**
		 * @return whether a transaction was created by this aspect,
		 * or whether we just have a placeholder to keep ThreadLocal
		 * stack integrity
		 */
		public boolean hasTransaction() {
			return transactionStatus != null;
		}

		/**
		 * Return a String representation of this joinpoint (usually a Method call)
		 * for use in logging.
		 */
		public String joinpointIdentification() {
			return methodIdentification(this.method);
		}

		public void newTransactionStatus(TransactionStatus status) {
			this.transactionStatus = status;
		}

		private void bindToThread() {
			// Expose current TransactionStatus, preserving any existing transactionStatus for
			// restoration after this transaction is complete.
			oldTransactionInfo = (TransactionInfo) currentTransactionInfo.get();
			currentTransactionInfo.set(this);
		}

		private void restoreThreadLocalStatus() {
			// Use stack to restore old transaction TransactionInfo.
			// Will be <code>null</code> if none was set.
			currentTransactionInfo.set(oldTransactionInfo);
		}

		public TransactionStatus getTransactionStatus() {
			return this.transactionStatus;
		}

		public TransactionAttribute getTransactionAttribute() {
			return this.transactionAttribute;
		}
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -