From b9935e9fe31888cecc06ec04174e87edee3da7f0 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 1 Jul 2014 16:29:40 +0200 Subject: [PATCH] BeanFactoryAnnotationUtils consistently applies bean name fallback when no BeanDefinition present Issue: SPR-11915 (cherry picked from commit f8b6114) --- .../BeanFactoryAnnotationUtils.java | 11 +++-- ...ationTransactionNamespaceHandlerTests.java | 10 +++-- .../EnableTransactionManagementTests.java | 41 ++++++++++++++++++- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/BeanFactoryAnnotationUtils.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/BeanFactoryAnnotationUtils.java index 5b604fd2632..9637abc94b4 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/BeanFactoryAnnotationUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/BeanFactoryAnnotationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 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. @@ -34,6 +34,7 @@ import org.springframework.util.ObjectUtils; * Spring's {@link Qualifier @Qualifier} annotation. * * @author Chris Beams + * @author Juergen Hoeller * @since 3.1.2 * @see BeanFactoryUtils */ @@ -90,9 +91,13 @@ public class BeanFactoryAnnotationUtils { if (matchingBean != null) { return matchingBean; } + else if (bf.containsBean(qualifier)) { + // Fallback: target bean at least found by bean name - probably a manually registered singleton. + return bf.getBean(qualifier, beanType); + } else { throw new NoSuchBeanDefinitionException(qualifier, "No matching " + beanType.getSimpleName() + - " bean found for qualifier '" + qualifier + "' - neither qualifier " + "match nor bean name match!"); + " bean found for qualifier '" + qualifier + "' - neither qualifier match nor bean name match!"); } } @@ -128,7 +133,7 @@ public class BeanFactoryAnnotationUtils { } } catch (NoSuchBeanDefinitionException ex) { - // ignore - can't compare qualifiers for a manually registered singleton object + // Ignore - can't compare qualifiers for a manually registered singleton object } } return false; diff --git a/spring-tx/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionNamespaceHandlerTests.java b/spring-tx/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionNamespaceHandlerTests.java index 92f1ed65142..311038d750d 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionNamespaceHandlerTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/annotation/AnnotationTransactionNamespaceHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -55,7 +55,7 @@ public class AnnotationTransactionNamespaceHandlerTests extends TestCase { public void testIsProxy() throws Exception { TransactionalTestBean bean = getTestBean(); assertTrue("testBean is not a proxy", AopUtils.isAopProxy(bean)); - Map services = this.context.getBeansWithAnnotation(Service.class); + Map services = this.context.getBeansWithAnnotation(Service.class); assertTrue("Stereotype annotation not visible", services.containsKey("testBean")); } @@ -110,7 +110,7 @@ public class AnnotationTransactionNamespaceHandlerTests extends TestCase { public static class TransactionalTestBean { @Transactional(readOnly = true) - public Collection findAllFoos() { + public Collection findAllFoos() { return null; } @@ -118,6 +118,10 @@ public class AnnotationTransactionNamespaceHandlerTests extends TestCase { public void saveFoo() { } + @Transactional("qualifiedTransactionManager") + public void saveQualifiedFoo() { + } + @Transactional public void exceptional(Throwable t) throws Throwable { throw t; diff --git a/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java b/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java index 8a35bb7d55c..3ad212dabc1 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -21,6 +21,8 @@ import java.util.Map; import org.junit.Test; import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AdviceMode; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -33,10 +35,13 @@ import org.springframework.transaction.annotation.AnnotationTransactionNamespace import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import javax.annotation.PostConstruct; + /** * Tests demonstrating use of @EnableTransactionManagement @Configuration classes. * * @author Chris Beams + * @author Stephane Nicoll * @since 3.1 */ public class EnableTransactionManagementTests { @@ -101,6 +106,21 @@ public class EnableTransactionManagementTests { } } + @Test + public void spr11915() { + AnnotationConfigApplicationContext ctx = + new AnnotationConfigApplicationContext(Spr11915Config.class); + + TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class); + bean.saveQualifiedFoo(); + + CallCountingTransactionManager txManager = ctx + .getBean("qualifiedTransactionManager", CallCountingTransactionManager.class); + assertThat(txManager.begun, equalTo(1)); + assertThat(txManager.commits, equalTo(1)); + assertThat(txManager.rollbacks, equalTo(0)); + } + @Configuration @EnableTransactionManagement @@ -118,6 +138,25 @@ public class EnableTransactionManagementTests { static class EnableAspectJTxConfig { } + @Configuration + @EnableTransactionManagement + static class Spr11915Config { + + @Autowired + private ConfigurableApplicationContext applicationContext; + + @PostConstruct + public void initializeApp() { + applicationContext.getBeanFactory().registerSingleton( + "qualifiedTransactionManager", new CallCountingTransactionManager()); + } + + @Bean + public TransactionalTestBean testBean() { + return new TransactionalTestBean(); + } + } + @Configuration static class TxManagerConfig {