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 eb691a14fd..6590100488 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 @@ -26,6 +26,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.AutowireCandidateQualifier; import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.ObjectUtils; /** @@ -113,6 +114,7 @@ public class BeanFactoryAnnotationUtils { if (bf.containsBean(beanName)) { try { BeanDefinition bd = bf.getMergedBeanDefinition(beanName); + // Explicit qualifier metadata on bean definition? (typically in XML definition) if (bd instanceof AbstractBeanDefinition) { AbstractBeanDefinition abd = (AbstractBeanDefinition) bd; AutowireCandidateQualifier candidate = abd.getQualifier(Qualifier.class.getName()); @@ -121,15 +123,24 @@ public class BeanFactoryAnnotationUtils { return true; } } + // Corresponding qualifier on factory method? (typically in configuration class) if (bd instanceof RootBeanDefinition) { Method factoryMethod = ((RootBeanDefinition) bd).getResolvedFactoryMethod(); if (factoryMethod != null) { - Qualifier targetAnnotation = factoryMethod.getAnnotation(Qualifier.class); - if (targetAnnotation != null && qualifier.equals(targetAnnotation.value())) { - return true; + Qualifier targetAnnotation = AnnotationUtils.getAnnotation(factoryMethod, Qualifier.class); + if (targetAnnotation != null) { + return qualifier.equals(targetAnnotation.value()); } } } + // Corresponding qualifier on bean implementation class? (for custom user types) + Class beanType = bf.getType(beanName); + if (beanType != null) { + Qualifier targetAnnotation = AnnotationUtils.getAnnotation(beanType, Qualifier.class); + if (targetAnnotation != null) { + return qualifier.equals(targetAnnotation.value()); + } + } } catch (NoSuchBeanDefinitionException ex) { // Ignore - can't compare qualifiers for a manually registered singleton object diff --git a/spring-tx/src/test/java/org/springframework/transaction/config/AnnotationDrivenTests.java b/spring-tx/src/test/java/org/springframework/transaction/config/AnnotationDrivenTests.java index 3e561c04e6..f58d648c6c 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/config/AnnotationDrivenTests.java +++ b/spring-tx/src/test/java/org/springframework/transaction/config/AnnotationDrivenTests.java @@ -20,10 +20,10 @@ import java.io.Serializable; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; - import org.junit.Test; import org.springframework.aop.support.AopUtils; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -47,8 +47,16 @@ public class AnnotationDrivenTests { @Test public void withConfigurationClass() throws Exception { + ApplicationContext parent = new AnnotationConfigApplicationContext(TransactionManagerConfiguration.class); + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"annotationDrivenConfigurationClassTests.xml"}, getClass(), parent); + doTestWithMultipleTransactionManagers(context); + } + + @Test + public void withAnnotatedTransactionManagers() throws Exception { AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext(); - parent.register(TransactionManagerConfiguration.class); + parent.registerBeanDefinition("transactionManager1", new RootBeanDefinition(SynchTransactionManager.class)); + parent.registerBeanDefinition("transactionManager2", new RootBeanDefinition(NoSynchTransactionManager.class)); parent.refresh(); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"annotationDrivenConfigurationClassTests.xml"}, getClass(), parent); doTestWithMultipleTransactionManagers(context); diff --git a/spring-tx/src/test/java/org/springframework/transaction/config/NoSynch.java b/spring-tx/src/test/java/org/springframework/transaction/config/NoSynch.java new file mode 100644 index 0000000000..828e835e1d --- /dev/null +++ b/spring-tx/src/test/java/org/springframework/transaction/config/NoSynch.java @@ -0,0 +1,31 @@ +/* + * Copyright 2002-2015 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.transaction.config; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import org.springframework.beans.factory.annotation.Qualifier; + +/** + * @author Juergen Hoeller + */ +@Qualifier("noSynch") +@Retention(RetentionPolicy.RUNTIME) +public @interface NoSynch { + +} diff --git a/spring-tx/src/test/java/org/springframework/transaction/config/NoSynchTransactionManager.java b/spring-tx/src/test/java/org/springframework/transaction/config/NoSynchTransactionManager.java new file mode 100644 index 0000000000..1f6ec382af --- /dev/null +++ b/spring-tx/src/test/java/org/springframework/transaction/config/NoSynchTransactionManager.java @@ -0,0 +1,32 @@ +/* + * Copyright 2002-2015 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.transaction.config; + +import org.springframework.tests.transaction.CallCountingTransactionManager; + +/** + * @author Juergen Hoeller + */ +@NoSynch +@SuppressWarnings("serial") +public class NoSynchTransactionManager extends CallCountingTransactionManager { + + public NoSynchTransactionManager() { + setTransactionSynchronization(CallCountingTransactionManager.SYNCHRONIZATION_NEVER); + } + +} diff --git a/spring-tx/src/test/java/org/springframework/transaction/config/SynchTransactionManager.java b/spring-tx/src/test/java/org/springframework/transaction/config/SynchTransactionManager.java new file mode 100644 index 0000000000..65c4496b47 --- /dev/null +++ b/spring-tx/src/test/java/org/springframework/transaction/config/SynchTransactionManager.java @@ -0,0 +1,29 @@ +/* + * Copyright 2002-2015 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.transaction.config; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.tests.transaction.CallCountingTransactionManager; + +/** + * @author Juergen Hoeller + */ +@Qualifier("synch") +@SuppressWarnings("serial") +public class SynchTransactionManager extends CallCountingTransactionManager { + +} diff --git a/spring-tx/src/test/java/org/springframework/transaction/config/TransactionManagerConfiguration.java b/spring-tx/src/test/java/org/springframework/transaction/config/TransactionManagerConfiguration.java index 965a0db01e..fb3b21f42d 100644 --- a/spring-tx/src/test/java/org/springframework/transaction/config/TransactionManagerConfiguration.java +++ b/spring-tx/src/test/java/org/springframework/transaction/config/TransactionManagerConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 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. @@ -35,7 +35,7 @@ public class TransactionManagerConfiguration { } @Bean - @Qualifier("noSynch") + @NoSynch public PlatformTransactionManager transactionManager2() { CallCountingTransactionManager tm = new CallCountingTransactionManager(); tm.setTransactionSynchronization(CallCountingTransactionManager.SYNCHRONIZATION_NEVER);