From f94645de17e11d7e15b18e4080a29fb97016eb0d Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 18 Nov 2025 13:36:29 +0100 Subject: [PATCH] Narrow Aware interface exclusion check to BeanFactoryAware only Closes gh-35835 (cherry picked from commit de5b9aab55f40365212949883f58d08bc6ed58a3) --- ...AbstractFallbackJCacheOperationSource.java | 6 ++-- .../AbstractFallbackCacheOperationSource.java | 6 ++-- ...actFallbackTransactionAttributeSource.java | 6 ++-- ...tationTransactionAttributeSourceTests.java | 28 +++++++++++++++---- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/AbstractFallbackJCacheOperationSource.java b/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/AbstractFallbackJCacheOperationSource.java index ed65ed263fd..aa9d5997c4b 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/AbstractFallbackJCacheOperationSource.java +++ b/spring-context-support/src/main/java/org/springframework/cache/jcache/interceptor/AbstractFallbackJCacheOperationSource.java @@ -25,7 +25,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.support.AopUtils; -import org.springframework.beans.factory.Aware; +import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.core.MethodClassKey; import org.springframework.lang.Nullable; import org.springframework.util.ReflectionUtils; @@ -98,8 +98,8 @@ public abstract class AbstractFallbackJCacheOperationSource implements JCacheOpe if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } - // Skip methods declared on BeanFactoryAware and co. - if (method.getDeclaringClass().isInterface() && Aware.class.isAssignableFrom(method.getDeclaringClass())) { + // Skip setBeanFactory method on BeanFactoryAware. + if (method.getDeclaringClass() == BeanFactoryAware.class) { return null; } diff --git a/spring-context/src/main/java/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java b/spring-context/src/main/java/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java index 548b9c15d56..ec3384a1813 100644 --- a/spring-context/src/main/java/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java +++ b/spring-context/src/main/java/org/springframework/cache/interceptor/AbstractFallbackCacheOperationSource.java @@ -27,7 +27,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.support.AopUtils; -import org.springframework.beans.factory.Aware; +import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.core.MethodClassKey; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; @@ -140,8 +140,8 @@ public abstract class AbstractFallbackCacheOperationSource implements CacheOpera if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } - // Skip methods declared on BeanFactoryAware and co. - if (method.getDeclaringClass().isInterface() && Aware.class.isAssignableFrom(method.getDeclaringClass())) { + // Skip setBeanFactory method on BeanFactoryAware. + if (method.getDeclaringClass() == BeanFactoryAware.class) { return null; } diff --git a/spring-tx/src/main/java/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java b/spring-tx/src/main/java/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java index f5a60c2e33b..3848f3b76e5 100644 --- a/spring-tx/src/main/java/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java +++ b/spring-tx/src/main/java/org/springframework/transaction/interceptor/AbstractFallbackTransactionAttributeSource.java @@ -25,7 +25,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.aop.support.AopUtils; -import org.springframework.beans.factory.Aware; +import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.context.EmbeddedValueResolverAware; import org.springframework.core.MethodClassKey; import org.springframework.lang.Nullable; @@ -167,8 +167,8 @@ public abstract class AbstractFallbackTransactionAttributeSource if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } - // Skip methods declared on BeanFactoryAware and co. - if (method.getDeclaringClass().isInterface() && Aware.class.isAssignableFrom(method.getDeclaringClass())) { + // Skip setBeanFactory method on BeanFactoryAware. + if (method.getDeclaringClass() == BeanFactoryAware.class) { return null; } diff --git a/spring-tx/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSourceTests.java b/spring-tx/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSourceTests.java index a6a6f4de37b..d428da79fc5 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSourceTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionAttributeSourceTests.java @@ -32,6 +32,7 @@ import org.junit.jupiter.api.Test; import org.springframework.aop.framework.Advised; import org.springframework.aop.framework.ProxyFactory; +import org.springframework.beans.factory.BeanNameAware; import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.testfixture.io.SerializationTestUtils; @@ -59,6 +60,7 @@ class AnnotationTransactionAttributeSourceTests { private final AnnotationTransactionAttributeSource attributeSource = new AnnotationTransactionAttributeSource(); + @Test void serializable() throws Exception { TestBean1 tb = new TestBean1(); @@ -123,6 +125,10 @@ class AnnotationTransactionAttributeSourceTests { void transactionAttributeDeclaredOnInterfaceMethodOnly() { TransactionAttribute actual = getTransactionAttribute(TestBean2.class, ITestBean2.class, "getAge"); assertThat(actual).satisfies(hasNoRollbackRule()); + actual = getTransactionAttribute(TestBean2.class, ITestBean2X.class, "getAge"); + assertThat(actual).satisfies(hasNoRollbackRule()); + actual = getTransactionAttribute(ITestBean2X.class, ITestBean2X.class, "getAge"); + assertThat(actual).satisfies(hasNoRollbackRule()); } /** @@ -249,6 +255,7 @@ class AnnotationTransactionAttributeSourceTests { assertThat(actual.isReadOnly()).isTrue(); } + @Nested class JtaAttributeTests { @@ -276,6 +283,7 @@ class AnnotationTransactionAttributeSourceTests { assertThat(getNameAttr.getPropagationBehavior()).isEqualTo(TransactionAttribute.PROPAGATION_SUPPORTS); } + static class JtaAnnotatedBean1 implements ITestBean1 { private String name; @@ -305,7 +313,6 @@ class AnnotationTransactionAttributeSourceTests { } } - @jakarta.transaction.Transactional(jakarta.transaction.Transactional.TxType.SUPPORTS) static class JtaAnnotatedBean2 implements ITestBean1 { @@ -362,7 +369,6 @@ class AnnotationTransactionAttributeSourceTests { } } - @jakarta.transaction.Transactional(jakarta.transaction.Transactional.TxType.SUPPORTS) interface ITestJta { @@ -375,9 +381,9 @@ class AnnotationTransactionAttributeSourceTests { void setName(String name); } - } + @Nested class Ejb3AttributeTests { @@ -448,7 +454,6 @@ class AnnotationTransactionAttributeSourceTests { } } - @jakarta.ejb.TransactionAttribute(TransactionAttributeType.SUPPORTS) static class Ejb3AnnotatedBean2 implements ITestBean1 { @@ -506,6 +511,7 @@ class AnnotationTransactionAttributeSourceTests { } } + @Nested class GroovyTests { @@ -519,6 +525,7 @@ class AnnotationTransactionAttributeSourceTests { assertThat(attributeSource.getTransactionAttribute(getMetaClassMethod, GroovyTestBean.class)).isNull(); } + @Transactional static class GroovyTestBean implements ITestBean1, GroovyObject { @@ -571,6 +578,7 @@ class AnnotationTransactionAttributeSourceTests { } } + private Consumer hasRollbackRules(RollbackRuleAttribute... rollbackRuleAttributes) { return transactionAttribute -> { RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute(); @@ -626,7 +634,12 @@ class AnnotationTransactionAttributeSourceTests { } - interface ITestBean2X extends ITestBean2 { + interface ITestBean2X extends ITestBean2, BeanNameAware { + + @Transactional + int getAge(); + + void setAge(int age); String getName(); @@ -735,6 +748,10 @@ class AnnotationTransactionAttributeSourceTests { this.age = age; } + @Override + public void setBeanName(String name) { + } + @Override public String getName() { return name; @@ -917,6 +934,7 @@ class AnnotationTransactionAttributeSourceTests { } } + @Transactional(label = {"retryable", "long-running"}) static class TestBean11 {