Skip to content

Commit 89b3651

Browse files
committed
TransactionInterceptor avoids reflective method search for method identification
As of Spring 3.0.4, we were trying to expose the target method signature as transaction name. Unfortunately, the algorithm called the ClassUtils.getMostSpecificMethod helper method which performs a quite expensive reflective search. As of this commit, we're simply concatenating the target class name with the method name, accepting the use of the concrete target class (which is arguably more meaningful for monitoring anyway) even when the method implementation actually sits on a base class. Issue: SPR-9802
1 parent abf341c commit 89b3651

File tree

3 files changed

+23
-25
lines changed

3 files changed

+23
-25
lines changed

spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAspectSupport.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import org.springframework.transaction.PlatformTransactionManager;
3434
import org.springframework.transaction.TransactionStatus;
3535
import org.springframework.transaction.TransactionSystemException;
36-
import org.springframework.util.ClassUtils;
3736
import org.springframework.util.StringUtils;
3837

3938
/**
@@ -260,11 +259,11 @@ else if (this.beanFactory instanceof ListableBeanFactory) {
260259
/**
261260
* Create a transaction if necessary, based on the given method and class.
262261
* <p>Performs a default TransactionAttribute lookup for the given method.
263-
* @param method method about to execute
264-
* @param targetClass class the method is on
262+
* @param method the method about to execute
263+
* @param targetClass the class that the method is being invoked on
265264
* @return a TransactionInfo object, whether or not a transaction was created.
266-
* The hasTransaction() method on TransactionInfo can be used to tell if there
267-
* was a transaction created.
265+
* The <code>hasTransaction()</code> method on TransactionInfo can be used to
266+
* tell if there was a transaction created.
268267
* @see #getTransactionAttributeSource()
269268
*/
270269
protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {
@@ -279,25 +278,24 @@ protected TransactionInfo createTransactionIfNecessary(Method method, Class targ
279278
* for use in logging. Can be overridden in subclasses to provide a
280279
* different identifier for the given method.
281280
* @param method the method we're interested in
282-
* @param targetClass class the method is on
283-
* @return log message identifying this method
281+
* @param targetClass the class that the method is being invoked on
282+
* @return a String representation identifying this method
284283
* @see org.springframework.util.ClassUtils#getQualifiedMethodName
285284
*/
286285
protected String methodIdentification(Method method, Class targetClass) {
287286
String simpleMethodId = methodIdentification(method);
288287
if (simpleMethodId != null) {
289288
return simpleMethodId;
290289
}
291-
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
292-
return ClassUtils.getQualifiedMethodName(specificMethod);
290+
return (targetClass != null ? targetClass : method.getDeclaringClass()).getName() + "." + method.getName();
293291
}
294292

295293
/**
296294
* Convenience method to return a String representation of this Method
297295
* for use in logging. Can be overridden in subclasses to provide a
298296
* different identifier for the given method.
299297
* @param method the method we're interested in
300-
* @return log message identifying this method
298+
* @return a String representation identifying this method
301299
* @deprecated in favor of {@link #methodIdentification(Method, Class)}
302300
*/
303301
@Deprecated

spring-tx/src/main/java/org/springframework/transaction/interceptor/TransactionAttributeSource.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,23 +19,25 @@
1919
import java.lang.reflect.Method;
2020

2121
/**
22-
* Interface used by TransactionInterceptor. Implementations know
23-
* how to source transaction attributes, whether from configuration,
24-
* metadata attributes at source level, or anywhere else.
22+
* Strategy interface used by {@link TransactionInterceptor} for metadata retrieval.
23+
*
24+
* <p>Implementations know how to source transaction attributes, whether from configuration,
25+
* metadata attributes at source level (such as Java 5 annotations), or anywhere else.
2526
*
2627
* @author Rod Johnson
2728
* @since 15.04.2003
2829
* @see TransactionInterceptor#setTransactionAttributeSource
2930
* @see TransactionProxyFactoryBean#setTransactionAttributeSource
31+
* @see org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
3032
*/
3133
public interface TransactionAttributeSource {
3234

3335
/**
34-
* Return the transaction attribute for this method.
35-
* Return null if the method is non-transactional.
36-
* @param method method
37-
* @param targetClass target class. May be <code>null</code>, in which
38-
* case the declaring class of the method must be used.
36+
* Return the transaction attribute for the given method,
37+
* or <code>null</code> if the method is non-transactional.
38+
* @param method the method to introspect
39+
* @param targetClass the target class. May be <code>null</code>,
40+
* in which case the declaring class of the method must be used.
3941
* @return TransactionAttribute the matching transaction attribute,
4042
* or <code>null</code> if none found
4143
*/

spring-tx/src/test/java/org/springframework/transaction/interceptor/BeanFactoryTransactionTests.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -127,16 +127,14 @@ private void doTestGetsAreNotTransactional(final ITestBean testBean) {
127127
final TransactionStatus ts = (TransactionStatus) statusControl.getMock();
128128
ptm = new PlatformTransactionManager() {
129129
private boolean invoked;
130-
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
130+
public TransactionStatus getTransaction(TransactionDefinition def) throws TransactionException {
131131
if (invoked) {
132132
throw new IllegalStateException("getTransaction should not get invoked more than once");
133133
}
134134
invoked = true;
135-
System.out.println(definition.getName());
136-
if (!((definition.getName().indexOf(TestBean.class.getName()) != -1) &&
137-
(definition.getName().indexOf("setAge") != -1))) {
135+
if (!(def.getName().contains(DerivedTestBean.class.getName()) && def.getName().contains("setAge"))) {
138136
throw new IllegalStateException(
139-
"transaction name should contain class and method name: " + definition.getName());
137+
"transaction name should contain class and method name: " + def.getName());
140138
}
141139
return ts;
142140
}

0 commit comments

Comments
 (0)