📄 transactionaspectsupport.java
字号:
// 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 + -