diff --git a/spring-core/src/main/java/org/springframework/util/ClassUtils.java b/spring-core/src/main/java/org/springframework/util/ClassUtils.java index 0035e1ad86..9ae3c1d4b4 100644 --- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java +++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java @@ -766,12 +766,28 @@ public abstract class ClassUtils { return method; } + /** + * Determine whether the given method is declared by the user or at least pointing to + * a user-declared method. + *

Checks {@link Method#isSynthetic()} (for implementation methods) as well as the + * {@code GroovyObject} interface (for interface methods; on an implementation class, + * implementations of the {@code GroovyObject} methods will be marked as synthetic anyway). + * Note that, despite being synthetic, bridge methods ({@link Method#isBridge()}) are considered + * as user-level methods since they are eventually pointing to a user-declared generic method. + * @param method the method to check + * @return {@code true} if the method can be considered as user-declared; [@code false} otherwise + */ + public static boolean isUserLevelMethod(Method method) { + return (method.isBridge() || + (!method.isSynthetic() && !method.getDeclaringClass().getName().equals("groovy.lang.GroovyObject"))); + } + /** * Determine whether the given method is overridable in the given target class. * @param method the method to check * @param targetClass the target class to check against */ - private static boolean isOverridable(Method method, Class targetClass) { + private static boolean isOverridable(Method method, Class targetClass) { if (Modifier.isPrivate(method.getModifiers())) { return false; } diff --git a/spring-tx/src/main/java/org/springframework/transaction/interceptor/MatchAlwaysTransactionAttributeSource.java b/spring-tx/src/main/java/org/springframework/transaction/interceptor/MatchAlwaysTransactionAttributeSource.java index e27ee94bf5..90c62d3f9f 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/interceptor/MatchAlwaysTransactionAttributeSource.java +++ b/spring-tx/src/main/java/org/springframework/transaction/interceptor/MatchAlwaysTransactionAttributeSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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,6 +19,7 @@ package org.springframework.transaction.interceptor; import java.io.Serializable; import java.lang.reflect.Method; +import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; /** @@ -52,7 +53,7 @@ public class MatchAlwaysTransactionAttributeSource implements TransactionAttribu @Override public TransactionAttribute getTransactionAttribute(Method method, Class targetClass) { - return this.transactionAttribute; + return (ClassUtils.isUserLevelMethod(method) ? this.transactionAttribute : null); } diff --git a/spring-tx/src/main/java/org/springframework/transaction/interceptor/NameMatchTransactionAttributeSource.java b/spring-tx/src/main/java/org/springframework/transaction/interceptor/NameMatchTransactionAttributeSource.java index 9d2b5debc8..83b6cd0f6a 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/interceptor/NameMatchTransactionAttributeSource.java +++ b/spring-tx/src/main/java/org/springframework/transaction/interceptor/NameMatchTransactionAttributeSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -26,6 +26,7 @@ import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.PatternMatchUtils; @@ -100,7 +101,11 @@ public class NameMatchTransactionAttributeSource implements TransactionAttribute @Override public TransactionAttribute getTransactionAttribute(Method method, Class targetClass) { - // look for direct name match + if (!ClassUtils.isUserLevelMethod(method)) { + return null; + } + + // Look for direct name match. String methodName = method.getName(); TransactionAttribute attr = this.nameMap.get(methodName);