DefaultTransactionAttribute stores descriptor (method identification)
Issue: SPR-14760
This commit is contained in:
parent
67a5ff02ac
commit
52b029d71d
|
|
@ -511,8 +511,21 @@ public abstract class ClassUtils {
|
|||
* @return the qualified name of the method
|
||||
*/
|
||||
public static String getQualifiedMethodName(Method method) {
|
||||
return getQualifiedMethodName(method, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the qualified name of the given method, consisting of
|
||||
* fully qualified interface/class name + "." + method name.
|
||||
* @param method the method
|
||||
* @param clazz the clazz that the method is being invoked on
|
||||
* (may be {@code null} to indicate the method's declaring class)
|
||||
* @return the qualified name of the method
|
||||
* @since 4.3.4
|
||||
*/
|
||||
public static String getQualifiedMethodName(Method method, Class<?> clazz) {
|
||||
Assert.notNull(method, "Method must not be null");
|
||||
return method.getDeclaringClass().getName() + "." + method.getName();
|
||||
return (clazz != null ? clazz : method.getDeclaringClass()).getName() + '.' + method.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -640,10 +653,10 @@ public abstract class ClassUtils {
|
|||
return candidates.iterator().next();
|
||||
}
|
||||
else if (candidates.isEmpty()) {
|
||||
throw new IllegalStateException("Expected method not found: " + clazz + "." + methodName);
|
||||
throw new IllegalStateException("Expected method not found: " + clazz.getName() + '.' + methodName);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("No unique method found: " + clazz + "." + methodName);
|
||||
throw new IllegalStateException("No unique method found: " + clazz.getName() + '.' + methodName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -980,7 +993,7 @@ public abstract class ClassUtils {
|
|||
public static String addResourcePathToPackagePath(Class<?> clazz, String resourceName) {
|
||||
Assert.notNull(resourceName, "Resource name must not be null");
|
||||
if (!resourceName.startsWith("/")) {
|
||||
return classPackageAsResourcePath(clazz) + "/" + resourceName;
|
||||
return classPackageAsResourcePath(clazz) + '/' + resourceName;
|
||||
}
|
||||
return classPackageAsResourcePath(clazz) + resourceName;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,20 +97,22 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
|
|||
}
|
||||
else {
|
||||
// We need to work it out.
|
||||
TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
|
||||
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
|
||||
// Put it in the cache.
|
||||
if (txAtt == null) {
|
||||
if (txAttr == null) {
|
||||
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
Class<?> classToLog = (targetClass != null ? targetClass : method.getDeclaringClass());
|
||||
logger.debug("Adding transactional method '" + classToLog.getSimpleName() + "." +
|
||||
method.getName() + "' with attribute: " + txAtt);
|
||||
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
|
||||
if (txAttr instanceof DefaultTransactionAttribute) {
|
||||
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
|
||||
}
|
||||
this.attributeCache.put(cacheKey, txAtt);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
|
||||
}
|
||||
this.attributeCache.put(cacheKey, txAttr);
|
||||
}
|
||||
return txAtt;
|
||||
return txAttr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -148,27 +150,27 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
|
|||
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||
|
||||
// First try is the method in the target class.
|
||||
TransactionAttribute txAtt = findTransactionAttribute(specificMethod);
|
||||
if (txAtt != null) {
|
||||
return txAtt;
|
||||
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
|
||||
if (txAttr != null) {
|
||||
return txAttr;
|
||||
}
|
||||
|
||||
// Second try is the transaction attribute on the target class.
|
||||
txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
|
||||
if (txAtt != null && ClassUtils.isUserLevelMethod(method)) {
|
||||
return txAtt;
|
||||
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
|
||||
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
|
||||
return txAttr;
|
||||
}
|
||||
|
||||
if (specificMethod != method) {
|
||||
// Fallback is to look at the original method.
|
||||
txAtt = findTransactionAttribute(method);
|
||||
if (txAtt != null) {
|
||||
return txAtt;
|
||||
txAttr = findTransactionAttribute(method);
|
||||
if (txAttr != null) {
|
||||
return txAttr;
|
||||
}
|
||||
// Last fallback is the class of the original method.
|
||||
txAtt = findTransactionAttribute(method.getDeclaringClass());
|
||||
if (txAtt != null && ClassUtils.isUserLevelMethod(method)) {
|
||||
return txAtt;
|
||||
txAttr = findTransactionAttribute(method.getDeclaringClass());
|
||||
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
|
||||
return txAttr;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -19,10 +19,11 @@ package org.springframework.transaction.interceptor;
|
|||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
||||
/**
|
||||
* Transaction attribute that takes the EJB approach to rolling
|
||||
* back on runtime, but not checked, exceptions.
|
||||
* Spring's common transaction attribute implementation.
|
||||
* Rolls back on runtime, but not checked, exceptions by default.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @since 16.03.2003
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
|
|
@ -30,6 +31,8 @@ public class DefaultTransactionAttribute extends DefaultTransactionDefinition im
|
|||
|
||||
private String qualifier;
|
||||
|
||||
private String descriptor;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new DefaultTransactionAttribute, with default settings.
|
||||
|
|
@ -74,6 +77,7 @@ public class DefaultTransactionAttribute extends DefaultTransactionDefinition im
|
|||
* Associate a qualifier value with this transaction attribute.
|
||||
* <p>This may be used for choosing a corresponding transaction manager
|
||||
* to process this specific transaction.
|
||||
* @since 3.0
|
||||
*/
|
||||
public void setQualifier(String qualifier) {
|
||||
this.qualifier = qualifier;
|
||||
|
|
@ -81,12 +85,31 @@ public class DefaultTransactionAttribute extends DefaultTransactionDefinition im
|
|||
|
||||
/**
|
||||
* Return a qualifier value associated with this transaction attribute.
|
||||
* @since 3.0
|
||||
*/
|
||||
@Override
|
||||
public String getQualifier() {
|
||||
return this.qualifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a descriptor for this transaction attribute,
|
||||
* e.g. indicating where the attribute is applying.
|
||||
* @since 4.3.4
|
||||
*/
|
||||
public void setDescriptor(String descriptor) {
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a descriptor for this transaction attribute,
|
||||
* or {@code null} if none.
|
||||
* @since 4.3.4
|
||||
*/
|
||||
public String getDescriptor() {
|
||||
return this.descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default behavior is as with EJB: rollback on unchecked exception.
|
||||
* Additionally attempt to rollback on Error.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import org.springframework.transaction.TransactionStatus;
|
|||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -269,7 +270,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
|||
// If the transaction attribute is null, the method is non-transactional.
|
||||
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
|
||||
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
|
||||
final String joinpointIdentification = methodIdentification(method, targetClass);
|
||||
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
|
||||
|
||||
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
|
||||
// Standard transaction demarcation with getTransaction and commit/rollback calls.
|
||||
|
|
@ -385,17 +386,33 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
|||
return txManager;
|
||||
}
|
||||
|
||||
private String methodIdentification(Method method, Class<?> targetClass, TransactionAttribute txAttr) {
|
||||
String methodIdentification = methodIdentification(method, targetClass);
|
||||
if (methodIdentification == null) {
|
||||
if (txAttr instanceof DefaultTransactionAttribute) {
|
||||
methodIdentification = ((DefaultTransactionAttribute) txAttr).getDescriptor();
|
||||
}
|
||||
if (methodIdentification == null) {
|
||||
methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
|
||||
}
|
||||
}
|
||||
return methodIdentification;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <p>The default implementation returns {@code null}, indicating the
|
||||
* use of {@link DefaultTransactionAttribute#getDescriptor()} instead,
|
||||
* ending up as {@link ClassUtils#getQualifiedMethodName(Method, Class)}.
|
||||
* @param method the method we're interested in
|
||||
* @param targetClass the class that the method is being invoked on
|
||||
* @return a String representation identifying this method
|
||||
* @see org.springframework.util.ClassUtils#getQualifiedMethodName
|
||||
*/
|
||||
protected String methodIdentification(Method method, Class<?> targetClass) {
|
||||
return (targetClass != null ? targetClass : method.getDeclaringClass()).getName() + "." + method.getName();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ public class MapTransactionAttributeSource extends AbstractFallbackTransactionAt
|
|||
private final Map<Object, TransactionAttribute> attributeMap = new HashMap<>();
|
||||
|
||||
|
||||
public void register(Method method, TransactionAttribute txAtt) {
|
||||
this.attributeMap.put(method, txAtt);
|
||||
public void register(Method method, TransactionAttribute txAttr) {
|
||||
this.attributeMap.put(method, txAttr);
|
||||
}
|
||||
|
||||
public void register(Class<?> clazz, TransactionAttribute txAtt) {
|
||||
this.attributeMap.put(clazz, txAtt);
|
||||
public void register(Class<?> clazz, TransactionAttribute txAttr) {
|
||||
this.attributeMap.put(clazz, txAttr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue