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
|
* @return the qualified name of the method
|
||||||
*/
|
*/
|
||||||
public static String getQualifiedMethodName(Method 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");
|
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();
|
return candidates.iterator().next();
|
||||||
}
|
}
|
||||||
else if (candidates.isEmpty()) {
|
else if (candidates.isEmpty()) {
|
||||||
throw new IllegalStateException("Expected method not found: " + clazz + "." + methodName);
|
throw new IllegalStateException("Expected method not found: " + clazz.getName() + '.' + methodName);
|
||||||
}
|
}
|
||||||
else {
|
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) {
|
public static String addResourcePathToPackagePath(Class<?> clazz, String resourceName) {
|
||||||
Assert.notNull(resourceName, "Resource name must not be null");
|
Assert.notNull(resourceName, "Resource name must not be null");
|
||||||
if (!resourceName.startsWith("/")) {
|
if (!resourceName.startsWith("/")) {
|
||||||
return classPackageAsResourcePath(clazz) + "/" + resourceName;
|
return classPackageAsResourcePath(clazz) + '/' + resourceName;
|
||||||
}
|
}
|
||||||
return classPackageAsResourcePath(clazz) + resourceName;
|
return classPackageAsResourcePath(clazz) + resourceName;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,20 +97,22 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// We need to work it out.
|
// We need to work it out.
|
||||||
TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
|
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
|
||||||
// Put it in the cache.
|
// Put it in the cache.
|
||||||
if (txAtt == null) {
|
if (txAttr == null) {
|
||||||
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
|
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (logger.isDebugEnabled()) {
|
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
|
||||||
Class<?> classToLog = (targetClass != null ? targetClass : method.getDeclaringClass());
|
if (txAttr instanceof DefaultTransactionAttribute) {
|
||||||
logger.debug("Adding transactional method '" + classToLog.getSimpleName() + "." +
|
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
|
||||||
method.getName() + "' with attribute: " + txAtt);
|
|
||||||
}
|
}
|
||||||
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);
|
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||||
|
|
||||||
// First try is the method in the target class.
|
// First try is the method in the target class.
|
||||||
TransactionAttribute txAtt = findTransactionAttribute(specificMethod);
|
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
|
||||||
if (txAtt != null) {
|
if (txAttr != null) {
|
||||||
return txAtt;
|
return txAttr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second try is the transaction attribute on the target class.
|
// Second try is the transaction attribute on the target class.
|
||||||
txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
|
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
|
||||||
if (txAtt != null && ClassUtils.isUserLevelMethod(method)) {
|
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
|
||||||
return txAtt;
|
return txAttr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (specificMethod != method) {
|
if (specificMethod != method) {
|
||||||
// Fallback is to look at the original method.
|
// Fallback is to look at the original method.
|
||||||
txAtt = findTransactionAttribute(method);
|
txAttr = findTransactionAttribute(method);
|
||||||
if (txAtt != null) {
|
if (txAttr != null) {
|
||||||
return txAtt;
|
return txAttr;
|
||||||
}
|
}
|
||||||
// Last fallback is the class of the original method.
|
// Last fallback is the class of the original method.
|
||||||
txAtt = findTransactionAttribute(method.getDeclaringClass());
|
txAttr = findTransactionAttribute(method.getDeclaringClass());
|
||||||
if (txAtt != null && ClassUtils.isUserLevelMethod(method)) {
|
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
|
||||||
return txAtt;
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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;
|
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transaction attribute that takes the EJB approach to rolling
|
* Spring's common transaction attribute implementation.
|
||||||
* back on runtime, but not checked, exceptions.
|
* Rolls back on runtime, but not checked, exceptions by default.
|
||||||
*
|
*
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 16.03.2003
|
* @since 16.03.2003
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
|
|
@ -30,6 +31,8 @@ public class DefaultTransactionAttribute extends DefaultTransactionDefinition im
|
||||||
|
|
||||||
private String qualifier;
|
private String qualifier;
|
||||||
|
|
||||||
|
private String descriptor;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new DefaultTransactionAttribute, with default settings.
|
* 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.
|
* Associate a qualifier value with this transaction attribute.
|
||||||
* <p>This may be used for choosing a corresponding transaction manager
|
* <p>This may be used for choosing a corresponding transaction manager
|
||||||
* to process this specific transaction.
|
* to process this specific transaction.
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public void setQualifier(String qualifier) {
|
public void setQualifier(String qualifier) {
|
||||||
this.qualifier = qualifier;
|
this.qualifier = qualifier;
|
||||||
|
|
@ -81,12 +85,31 @@ public class DefaultTransactionAttribute extends DefaultTransactionDefinition im
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a qualifier value associated with this transaction attribute.
|
* Return a qualifier value associated with this transaction attribute.
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getQualifier() {
|
public String getQualifier() {
|
||||||
return this.qualifier;
|
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.
|
* The default behavior is as with EJB: rollback on unchecked exception.
|
||||||
* Additionally attempt to rollback on Error.
|
* Additionally attempt to rollback on Error.
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import org.springframework.transaction.TransactionStatus;
|
||||||
import org.springframework.transaction.TransactionSystemException;
|
import org.springframework.transaction.TransactionSystemException;
|
||||||
import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
|
import org.springframework.transaction.support.CallbackPreferringPlatformTransactionManager;
|
||||||
import org.springframework.transaction.support.TransactionCallback;
|
import org.springframework.transaction.support.TransactionCallback;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||||
import org.springframework.util.StringUtils;
|
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.
|
// If the transaction attribute is null, the method is non-transactional.
|
||||||
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
|
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
|
||||||
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
|
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
|
||||||
final String joinpointIdentification = methodIdentification(method, targetClass);
|
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
|
||||||
|
|
||||||
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
|
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
|
||||||
// Standard transaction demarcation with getTransaction and commit/rollback calls.
|
// Standard transaction demarcation with getTransaction and commit/rollback calls.
|
||||||
|
|
@ -385,17 +386,33 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
||||||
return txManager;
|
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
|
* Convenience method to return a String representation of this Method
|
||||||
* for use in logging. Can be overridden in subclasses to provide a
|
* for use in logging. Can be overridden in subclasses to provide a
|
||||||
* different identifier for the given method.
|
* 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 method the method we're interested in
|
||||||
* @param targetClass the class that the method is being invoked on
|
* @param targetClass the class that the method is being invoked on
|
||||||
* @return a String representation identifying this method
|
* @return a String representation identifying this method
|
||||||
* @see org.springframework.util.ClassUtils#getQualifiedMethodName
|
* @see org.springframework.util.ClassUtils#getQualifiedMethodName
|
||||||
*/
|
*/
|
||||||
protected String methodIdentification(Method method, Class<?> targetClass) {
|
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<>();
|
private final Map<Object, TransactionAttribute> attributeMap = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
public void register(Method method, TransactionAttribute txAtt) {
|
public void register(Method method, TransactionAttribute txAttr) {
|
||||||
this.attributeMap.put(method, txAtt);
|
this.attributeMap.put(method, txAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(Class<?> clazz, TransactionAttribute txAtt) {
|
public void register(Class<?> clazz, TransactionAttribute txAttr) {
|
||||||
this.attributeMap.put(clazz, txAtt);
|
this.attributeMap.put(clazz, txAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue