diff --git a/org.springframework.transaction/src/main/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSource.java b/org.springframework.transaction/src/main/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSource.java
index 607b3047d4c..ffebe02a1bf 100644
--- a/org.springframework.transaction/src/main/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSource.java
+++ b/org.springframework.transaction/src/main/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2009 the original author or authors.
+ * Copyright 2002-2010 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.
@@ -114,7 +114,7 @@ public class AnnotationTransactionAttributeSource extends AbstractFallbackTransa
}
@Override
- protected TransactionAttribute findTransactionAttribute(Class clazz) {
+ protected TransactionAttribute findTransactionAttribute(Class> clazz) {
return determineTransactionAttribute(clazz);
}
diff --git a/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java b/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java
index 01dbf705e6d..8ef4e5ef1fa 100644
--- a/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java
+++ b/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java
@@ -80,7 +80,7 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
* @return TransactionAttribute for this method, or null if the method
* is not transactional
*/
- public TransactionAttribute getTransactionAttribute(Method method, Class targetClass) {
+ public TransactionAttribute getTransactionAttribute(Method method, Class> targetClass) {
// First, see if we have a cached value.
Object cacheKey = getCacheKey(method, targetClass);
Object cached = this.attributeCache.get(cacheKey);
@@ -119,7 +119,7 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
* @param targetClass the target class (may be null)
* @return the cache key (never null)
*/
- protected Object getCacheKey(Method method, Class targetClass) {
+ protected Object getCacheKey(Method method, Class> targetClass) {
return new DefaultCacheKey(method, targetClass);
}
@@ -128,15 +128,17 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
* {@link #getTransactionAttribute} is effectively a caching decorator for this method.
* @see #getTransactionAttribute
*/
- private TransactionAttribute computeTransactionAttribute(Method method, Class targetClass) {
+ private TransactionAttribute computeTransactionAttribute(Method method, Class> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
+ // Ignore CGLIB subclasses - introspect the actual user class.
+ Class> userClass = ClassUtils.getUserClass(targetClass);
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
- Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
+ Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
// If we are dealing with method with generic parameters, find the original method.
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
@@ -181,7 +183,7 @@ public abstract class AbstractFallbackTransactionAttributeSource implements Tran
* @return all transaction attribute associated with this class
* (or null if none)
*/
- protected abstract TransactionAttribute findTransactionAttribute(Class clazz);
+ protected abstract TransactionAttribute findTransactionAttribute(Class> clazz);
/**
diff --git a/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/TransactionAttributeSource.java b/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/TransactionAttributeSource.java
index 3dcbf6a6fcb..14df0875b5e 100644
--- a/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/TransactionAttributeSource.java
+++ b/org.springframework.transaction/src/main/java/org/springframework/transaction/interceptor/TransactionAttributeSource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2006 the original author or authors.
+ * Copyright 2002-2010 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.
@@ -39,6 +39,6 @@ public interface TransactionAttributeSource {
* @return TransactionAttribute the matching transaction attribute,
* or null if none found
*/
- TransactionAttribute getTransactionAttribute(Method method, Class targetClass);
+ TransactionAttribute getTransactionAttribute(Method method, Class> targetClass);
}
diff --git a/org.springframework.transaction/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSourceTests.java b/org.springframework.transaction/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSourceTests.java
index 322a659bb47..9bd446fc87c 100644
--- a/org.springframework.transaction/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSourceTests.java
+++ b/org.springframework.transaction/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSourceTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2006 the original author or authors.
+ * Copyright 2002-2010 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.
@@ -95,6 +95,26 @@ public class AnnotationTransactionAttributeSourceTests {
assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
}
+ /**
+ * Test the important case where the invocation is on a proxied interface method
+ * but the attribute is defined on the target class.
+ */
+ @Test
+ public void testTransactionAttributeDeclaredOnCglibClassMethod() throws Exception {
+ Method classMethod = ITestBean.class.getMethod("getAge", (Class[]) null);
+ TestBean1 tb = new TestBean1();
+ ProxyFactory pf = new ProxyFactory(tb);
+ pf.setProxyTargetClass(true);
+ Object proxy = pf.getProxy();
+
+ AnnotationTransactionAttributeSource atas = new AnnotationTransactionAttributeSource();
+ TransactionAttribute actual = atas.getTransactionAttribute(classMethod, proxy.getClass());
+
+ RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
+ rbta.getRollbackRules().add(new RollbackRuleAttribute(Exception.class));
+ assertEquals(rbta.getRollbackRules(), ((RuleBasedTransactionAttribute) actual).getRollbackRules());
+ }
+
/**
* Test case where attribute is on the interface method.
*/
diff --git a/org.springframework.transaction/src/test/java/org/springframework/transaction/interceptor/MapTransactionAttributeSource.java b/org.springframework.transaction/src/test/java/org/springframework/transaction/interceptor/MapTransactionAttributeSource.java
index 35ef3bf103e..a260d3ef719 100644
--- a/org.springframework.transaction/src/test/java/org/springframework/transaction/interceptor/MapTransactionAttributeSource.java
+++ b/org.springframework.transaction/src/test/java/org/springframework/transaction/interceptor/MapTransactionAttributeSource.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2007 the original author or authors.
+ * Copyright 2002-2010 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.
@@ -27,25 +27,25 @@ import java.util.Map;
* @author Juergen Hoeller
*/
public class MapTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource {
-
- /** Map from Method or Clazz to TransactionAttribute */
- private final Map attributeMap = new HashMap();
-
- public void register(Method m, TransactionAttribute txAtt) {
- this.attributeMap.put(m, txAtt);
+
+ private final Map