@Transactional qualifiers work in unit tests as well (SPR-6892)

This commit is contained in:
Juergen Hoeller
2010-03-12 20:44:41 +00:00
parent 23cb161fb3
commit bb75662a7e
5 changed files with 163 additions and 84 deletions

View File

@@ -17,7 +17,6 @@
package org.springframework.transaction.interceptor;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.logging.Log;
@@ -28,18 +27,13 @@ import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.NamedThreadLocal;
import org.springframework.transaction.NoTransactionException;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.interceptor.TransactionAspectUtils;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -249,38 +243,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
}
String qualifier = txAttr.getQualifier();
if (StringUtils.hasLength(qualifier)) {
if (!(this.beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalStateException("BeanFactory required to be a ConfigurableListableBeanFactory " +
"for resolution of qualifier '" + qualifier + "': " + this.beanFactory.getClass());
}
ConfigurableListableBeanFactory bf = (ConfigurableListableBeanFactory) this.beanFactory;
Map<String, PlatformTransactionManager> tms =
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 (chosen != null) {
return chosen;
}
else {
throw new IllegalStateException(
"No matching PlatformTransactionManager bean found for qualifier '" + qualifier + "'");
}
return TransactionAspectUtils.getTransactionManager(this.beanFactory, qualifier);
}
else if (this.transactionManagerBeanName != null) {
return this.beanFactory.getBean(this.transactionManagerBeanName, PlatformTransactionManager.class);

View File

@@ -0,0 +1,102 @@
/*
* Copyright 2002-2010 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.interceptor;
import java.util.Map;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.annotation.Qualifier;
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.transaction.PlatformTransactionManager;
import org.springframework.util.ObjectUtils;
/**
* Utility methods for obtaining a PlatformTransactionManager by
* {@link TransactionAttribute#getQualifier() qualifier value}.
*
* @author Juergen Hoeller
* @since 3.0.2
*/
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 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
*/
public static PlatformTransactionManager getTransactionManager(BeanFactory beanFactory, String qualifier) {
if (beanFactory instanceof ConfigurableListableBeanFactory) {
// Full qualifier matching supported.
return getTransactionManager((ConfigurableListableBeanFactory) beanFactory, qualifier);
}
else if (beanFactory.containsBean(qualifier)) {
// Fallback: PlatformTransactionManager at least found by bean name.
return beanFactory.getBean(qualifier, PlatformTransactionManager.class);
}
else {
throw new IllegalStateException("No matching PlatformTransactionManager bean found for bean name '" +
qualifier + "'! (Note: Qualifier matching not supported because given BeanFactory does not " +
"implement ConfigurableListableBeanFactory.)");
}
}
/**
* Obtain a PlatformTransactionManager from the given BeanFactory,
* matching the given qualifier.
* @param beanFactory 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
*/
public static PlatformTransactionManager getTransactionManager(ConfigurableListableBeanFactory bf, String qualifier) {
Map<String, PlatformTransactionManager> tms =
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 (chosen != null) {
return chosen;
}
else {
throw new IllegalStateException("No matching PlatformTransactionManager bean found for qualifier '" +
qualifier + "' - neither qualifier match nor bean name match!");
}
}
}