@Transactional qualifier value matches against @Qualifier annotations on @Bean methods as well (SPR-7232)
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.transaction.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
@@ -25,6 +26,7 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
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.transaction.PlatformTransactionManager;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -64,7 +66,7 @@ public abstract class TransactionAspectUtils {
|
||||
/**
|
||||
* Obtain a PlatformTransactionManager from the given BeanFactory,
|
||||
* matching the given qualifier.
|
||||
* @param beanFactory the BeanFactory to get the PlatformTransactionManager bean from
|
||||
* @param bf the BeanFactory to get the PlatformTransactionManager bean from
|
||||
* @param qualifier the qualifier for selecting between multiple PlatformTransactionManager matches
|
||||
* @return the chosen PlatformTransactionManager (never <code>null</code>)
|
||||
* @throws IllegalStateException if no matching PlatformTransactionManager bean found
|
||||
@@ -74,20 +76,12 @@ public abstract class TransactionAspectUtils {
|
||||
BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, PlatformTransactionManager.class);
|
||||
PlatformTransactionManager chosen = null;
|
||||
for (String beanName : tms.keySet()) {
|
||||
if (bf.containsBeanDefinition(beanName)) {
|
||||
BeanDefinition bd = bf.getBeanDefinition(beanName);
|
||||
if (bd instanceof AbstractBeanDefinition) {
|
||||
AbstractBeanDefinition abd = (AbstractBeanDefinition) bd;
|
||||
AutowireCandidateQualifier candidate = abd.getQualifier(Qualifier.class.getName());
|
||||
if ((candidate != null && qualifier.equals(candidate.getAttribute(AutowireCandidateQualifier.VALUE_KEY))) ||
|
||||
qualifier.equals(beanName) || ObjectUtils.containsElement(bf.getAliases(beanName), qualifier)) {
|
||||
if (chosen != null) {
|
||||
throw new IllegalStateException("No unique PlatformTransactionManager bean found " +
|
||||
"for qualifier '" + qualifier + "'");
|
||||
}
|
||||
chosen = tms.get(beanName);
|
||||
}
|
||||
if (isQualifierMatch(qualifier, beanName, bf)) {
|
||||
if (chosen != null) {
|
||||
throw new IllegalStateException("No unique PlatformTransactionManager bean found " +
|
||||
"for qualifier '" + qualifier + "'");
|
||||
}
|
||||
chosen = tms.get(beanName);
|
||||
}
|
||||
}
|
||||
if (chosen != null) {
|
||||
@@ -99,4 +93,37 @@ public abstract class TransactionAspectUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether we have a qualifier match for the given candidate bean.
|
||||
* @param qualifier the qualifier that we are looking for
|
||||
* @param beanName the name of the candidate bean
|
||||
* @param bf the BeanFactory to get the bean definition from
|
||||
* @return <code>true</code> if either the bean definition (in the XML case)
|
||||
* or the bean's factory method (in the @Bean case) defines a matching qualifier
|
||||
* value (through <qualifier<> or @Qualifier)
|
||||
*/
|
||||
private static boolean isQualifierMatch(String qualifier, String beanName, ConfigurableListableBeanFactory bf) {
|
||||
if (bf.containsBeanDefinition(beanName)) {
|
||||
BeanDefinition bd = bf.getMergedBeanDefinition(beanName);
|
||||
if (bd instanceof AbstractBeanDefinition) {
|
||||
AbstractBeanDefinition abd = (AbstractBeanDefinition) bd;
|
||||
AutowireCandidateQualifier candidate = abd.getQualifier(Qualifier.class.getName());
|
||||
if ((candidate != null && qualifier.equals(candidate.getAttribute(AutowireCandidateQualifier.VALUE_KEY))) ||
|
||||
qualifier.equals(beanName) || ObjectUtils.containsElement(bf.getAliases(beanName), qualifier)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user