提交 52b029d7 编写于 作者: J Juergen Hoeller

DefaultTransactionAttribute stores descriptor (method identification)

Issue: SPR-14760
上级 67a5ff02
......@@ -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 {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isDebugEnabled()) {
Class<?> classToLog = (targetClass != null ? targetClass : method.getDeclaringClass());
logger.debug("Adding transactional method '" + classToLog.getSimpleName() + "." +
method.getName() + "' with attribute: " + txAtt);
logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAtt);
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;
}
}
......
/*
* 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);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册