Consider type-level qualifier annotations for transaction manager selection
Closes gh-24291
This commit is contained in:
parent
6461eec582
commit
14a461e795
|
@ -548,12 +548,32 @@ transaction managers, differentiated by the `order`, `account`, and `reactive-ac
|
||||||
qualifiers. The default `<tx:annotation-driven>` target bean name, `transactionManager`,
|
qualifiers. The default `<tx:annotation-driven>` target bean name, `transactionManager`,
|
||||||
is still used if no specifically qualified `TransactionManager` bean is found.
|
is still used if no specifically qualified `TransactionManager` bean is found.
|
||||||
|
|
||||||
|
[TIP]
|
||||||
|
====
|
||||||
|
If all transactional methods on the same class share the same qualifier, consider
|
||||||
|
declaring a type-level `org.springframework.beans.factory.annotation.Qualifier`
|
||||||
|
annotation instead. If its value matches the qualifier value (or bean name) of a
|
||||||
|
specific transaction manager, that transaction manager is going to be used for
|
||||||
|
transaction definitions without a specific qualifier on `@Transactional` itself.
|
||||||
|
|
||||||
|
Such a type-level qualifier can be declared on the concrete class, applying to
|
||||||
|
transaction definitions from a base class as well. This effectively overrides
|
||||||
|
the default transaction manager choice for any unqualified base class methods.
|
||||||
|
|
||||||
|
Last but not least, such a type-level bean qualifier can serve multiple purposes,
|
||||||
|
e.g. with a value of "order" it can be used for autowiring purposes (identifying
|
||||||
|
the order repository) as well as transaction manager selection, as long as the
|
||||||
|
target beans for autowiring as well as the associated transaction manager
|
||||||
|
definitions declare the same qualifier value. Such a qualifier value only needs
|
||||||
|
to be unique with a set of type-matching beans, not having to serve as an id.
|
||||||
|
====
|
||||||
|
|
||||||
[[tx-custom-attributes]]
|
[[tx-custom-attributes]]
|
||||||
== Custom Composed Annotations
|
== Custom Composed Annotations
|
||||||
|
|
||||||
If you find you repeatedly use the same attributes with `@Transactional` on many different
|
If you find you repeatedly use the same attributes with `@Transactional` on many different methods,
|
||||||
methods, xref:core/beans/classpath-scanning.adoc#beans-meta-annotations[Spring's meta-annotation support] lets you
|
xref:core/beans/classpath-scanning.adoc#beans-meta-annotations[Spring's meta-annotation support]
|
||||||
define custom composed annotations for your specific use cases. For example, consider the
|
lets you define custom composed annotations for your specific use cases. For example, consider the
|
||||||
following annotation definitions:
|
following annotation definitions:
|
||||||
|
|
||||||
[tabs]
|
[tabs]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.beans.factory.annotation;
|
package org.springframework.beans.factory.annotation;
|
||||||
|
|
||||||
|
import java.lang.reflect.AnnotatedElement;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -138,6 +139,19 @@ public abstract class BeanFactoryAnnotationUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the {@link Qualifier#value() qualifier value} for the given
|
||||||
|
* annotated element.
|
||||||
|
* @param annotatedElement the class, method or parameter to introspect
|
||||||
|
* @return the associated qualifier value, or {@code null} if none
|
||||||
|
* @since 6.2
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static String getQualifierValue(AnnotatedElement annotatedElement) {
|
||||||
|
Qualifier qualifier = AnnotationUtils.getAnnotation(annotatedElement, Qualifier.class);
|
||||||
|
return (qualifier != null ? qualifier.value() : null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the named bean declares a qualifier of the given name.
|
* Check whether the named bean declares a qualifier of the given name.
|
||||||
* @param qualifier the qualifier to match
|
* @param qualifier the qualifier to match
|
||||||
|
|
|
@ -139,6 +139,14 @@ public @interface Transactional {
|
||||||
* qualifier value (or the bean name) of a specific
|
* qualifier value (or the bean name) of a specific
|
||||||
* {@link org.springframework.transaction.TransactionManager TransactionManager}
|
* {@link org.springframework.transaction.TransactionManager TransactionManager}
|
||||||
* bean definition.
|
* bean definition.
|
||||||
|
* <p>Alternatively, as of 6.2, a type-level bean qualifier annotation with a
|
||||||
|
* {@link org.springframework.beans.factory.annotation.Qualifier#value() qualifier value}
|
||||||
|
* is also taken into account. If it matches the qualifier value (or bean name)
|
||||||
|
* of a specific transaction manager, that transaction manager is going to be used
|
||||||
|
* for transaction definitions without a specific qualifier on this attribute here.
|
||||||
|
* Such a type-level qualifier can be declared on the concrete class, applying
|
||||||
|
* to transaction definitions from a base class as well, effectively overriding
|
||||||
|
* the default transaction manager choice for any unqualified base class methods.
|
||||||
* @since 4.2
|
* @since 4.2
|
||||||
* @see #value
|
* @see #value
|
||||||
* @see org.springframework.transaction.PlatformTransactionManager
|
* @see org.springframework.transaction.PlatformTransactionManager
|
||||||
|
|
|
@ -35,6 +35,7 @@ import reactor.core.publisher.Mono;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
|
||||||
import org.springframework.core.CoroutinesUtils;
|
import org.springframework.core.CoroutinesUtils;
|
||||||
import org.springframework.core.KotlinDetector;
|
import org.springframework.core.KotlinDetector;
|
||||||
|
@ -349,7 +350,7 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
||||||
// If the transaction attribute is null, the method is non-transactional.
|
// If the transaction attribute is null, the method is non-transactional.
|
||||||
TransactionAttributeSource tas = getTransactionAttributeSource();
|
TransactionAttributeSource tas = getTransactionAttributeSource();
|
||||||
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
|
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
|
||||||
final TransactionManager tm = determineTransactionManager(txAttr);
|
final TransactionManager tm = determineTransactionManager(txAttr, targetClass);
|
||||||
|
|
||||||
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager rtm) {
|
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager rtm) {
|
||||||
boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
|
boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
|
||||||
|
@ -499,9 +500,19 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the specific transaction manager to use for the given transaction.
|
* Determine the specific transaction manager to use for the given transaction.
|
||||||
|
* @param txAttr the current transaction attribute
|
||||||
|
* @param targetClass the target class that the attribute has been declared on
|
||||||
|
* @since 6.2
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
|
protected TransactionManager determineTransactionManager(
|
||||||
|
@Nullable TransactionAttribute txAttr, @Nullable Class<?> targetClass) {
|
||||||
|
|
||||||
|
TransactionManager tm = determineTransactionManager(txAttr);
|
||||||
|
if (tm != null) {
|
||||||
|
return tm;
|
||||||
|
}
|
||||||
|
|
||||||
// Do not attempt to lookup tx manager if no tx attributes are set
|
// Do not attempt to lookup tx manager if no tx attributes are set
|
||||||
if (txAttr == null || this.beanFactory == null) {
|
if (txAttr == null || this.beanFactory == null) {
|
||||||
return getTransactionManager();
|
return getTransactionManager();
|
||||||
|
@ -511,7 +522,20 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
||||||
if (StringUtils.hasText(qualifier)) {
|
if (StringUtils.hasText(qualifier)) {
|
||||||
return determineQualifiedTransactionManager(this.beanFactory, qualifier);
|
return determineQualifiedTransactionManager(this.beanFactory, qualifier);
|
||||||
}
|
}
|
||||||
else if (StringUtils.hasText(this.transactionManagerBeanName)) {
|
else if (targetClass != null) {
|
||||||
|
// Consider type-level qualifier annotations for transaction manager selection
|
||||||
|
String typeQualifier = BeanFactoryAnnotationUtils.getQualifierValue(targetClass);
|
||||||
|
if (StringUtils.hasText(typeQualifier)) {
|
||||||
|
try {
|
||||||
|
return determineQualifiedTransactionManager(this.beanFactory, typeQualifier);
|
||||||
|
}
|
||||||
|
catch (NoSuchBeanDefinitionException ex) {
|
||||||
|
// Consider type qualifier as optional, proceed with regular resolution below.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.hasText(this.transactionManagerBeanName)) {
|
||||||
return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
|
return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -528,6 +552,16 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the specific transaction manager to use for the given transaction.
|
||||||
|
* @deprecated as of 6.2, in favor of {@link #determineTransactionManager(TransactionAttribute, Class)}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
@Nullable
|
||||||
|
protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private TransactionManager determineQualifiedTransactionManager(BeanFactory beanFactory, String qualifier) {
|
private TransactionManager determineQualifiedTransactionManager(BeanFactory beanFactory, String qualifier) {
|
||||||
TransactionManager txManager = this.transactionManagerCache.get(qualifier);
|
TransactionManager txManager = this.transactionManagerCache.get(qualifier);
|
||||||
if (txManager == null) {
|
if (txManager == null) {
|
||||||
|
@ -538,7 +572,6 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
|
||||||
return txManager;
|
return txManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private PlatformTransactionManager asPlatformTransactionManager(@Nullable Object transactionManager) {
|
private PlatformTransactionManager asPlatformTransactionManager(@Nullable Object transactionManager) {
|
||||||
if (transactionManager == null) {
|
if (transactionManager == null) {
|
||||||
|
|
|
@ -23,7 +23,9 @@ import java.util.Properties;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.aop.support.AopUtils;
|
import org.springframework.aop.support.AopUtils;
|
||||||
|
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.AdviceMode;
|
import org.springframework.context.annotation.AdviceMode;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
@ -46,6 +48,7 @@ import org.springframework.transaction.testfixture.CallCountingTransactionManage
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatException;
|
import static org.assertj.core.api.Assertions.assertThatException;
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
|
||||||
import static org.springframework.transaction.annotation.RollbackOn.ALL_EXCEPTIONS;
|
import static org.springframework.transaction.annotation.RollbackOn.ALL_EXCEPTIONS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -255,9 +258,34 @@ class EnableTransactionManagementTests {
|
||||||
assertThat(txManager.commits).isEqualTo(2);
|
assertThat(txManager.commits).isEqualTo(2);
|
||||||
assertThat(txManager.rollbacks).isEqualTo(0);
|
assertThat(txManager.rollbacks).isEqualTo(0);
|
||||||
|
|
||||||
|
assertThatExceptionOfType(NoUniqueBeanDefinitionException.class).isThrownBy(bean::findAllFoos);
|
||||||
|
|
||||||
ctx.close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void gh24291TransactionManagerViaQualifierAnnotation() {
|
||||||
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Gh24291Config.class);
|
||||||
|
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class);
|
||||||
|
CallCountingTransactionManager txManager = ctx.getBean("qualifiedTransactionManager", CallCountingTransactionManager.class);
|
||||||
|
|
||||||
|
bean.saveQualifiedFoo();
|
||||||
|
assertThat(txManager.begun).isEqualTo(1);
|
||||||
|
assertThat(txManager.commits).isEqualTo(1);
|
||||||
|
assertThat(txManager.rollbacks).isEqualTo(0);
|
||||||
|
|
||||||
|
bean.saveQualifiedFooWithAttributeAlias();
|
||||||
|
assertThat(txManager.begun).isEqualTo(2);
|
||||||
|
assertThat(txManager.commits).isEqualTo(2);
|
||||||
|
assertThat(txManager.rollbacks).isEqualTo(0);
|
||||||
|
|
||||||
|
bean.findAllFoos();
|
||||||
|
assertThat(txManager.begun).isEqualTo(3);
|
||||||
|
assertThat(txManager.commits).isEqualTo(3);
|
||||||
|
assertThat(txManager.rollbacks).isEqualTo(0);
|
||||||
|
|
||||||
|
ctx.close();
|
||||||
|
}
|
||||||
@Test
|
@Test
|
||||||
void spr14322FindsOnInterfaceWithInterfaceProxy() {
|
void spr14322FindsOnInterfaceWithInterfaceProxy() {
|
||||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Spr14322ConfigA.class);
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Spr14322ConfigA.class);
|
||||||
|
@ -352,6 +380,12 @@ class EnableTransactionManagementTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Qualifier("qualified")
|
||||||
|
public static class TransactionalTestBeanSubclass extends TransactionalTestBean {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
static class PlaceholderConfig {
|
static class PlaceholderConfig {
|
||||||
|
|
||||||
|
@ -535,6 +569,35 @@ class EnableTransactionManagementTests {
|
||||||
public TransactionalTestBean testBean() {
|
public TransactionalTestBean testBean() {
|
||||||
return new TransactionalTestBean();
|
return new TransactionalTestBean();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CallCountingTransactionManager otherTxManager() {
|
||||||
|
return new CallCountingTransactionManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableTransactionManagement
|
||||||
|
@Import(PlaceholderConfig.class)
|
||||||
|
static class Gh24291Config {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void initializeApp(ConfigurableApplicationContext applicationContext) {
|
||||||
|
applicationContext.getBeanFactory().registerSingleton(
|
||||||
|
"qualifiedTransactionManager", new CallCountingTransactionManager());
|
||||||
|
applicationContext.getBeanFactory().registerAlias("qualifiedTransactionManager", "qualified");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public TransactionalTestBeanSubclass testBean() {
|
||||||
|
return new TransactionalTestBeanSubclass();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CallCountingTransactionManager otherTxManager() {
|
||||||
|
return new CallCountingTransactionManager();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -116,15 +116,11 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
ti.setTransactionManager(ptm);
|
ti.setTransactionManager(ptm);
|
||||||
ti = SerializationTestUtils.serializeAndDeserialize(ti);
|
ti = SerializationTestUtils.serializeAndDeserialize(ti);
|
||||||
|
|
||||||
boolean condition3 = ti.getTransactionManager() instanceof SerializableTransactionManager;
|
assertThat(ti.getTransactionManager() instanceof SerializableTransactionManager).isTrue();
|
||||||
assertThat(condition3).isTrue();
|
assertThat(ti.getTransactionAttributeSource() instanceof CompositeTransactionAttributeSource).isTrue();
|
||||||
boolean condition2 = ti.getTransactionAttributeSource() instanceof CompositeTransactionAttributeSource;
|
|
||||||
assertThat(condition2).isTrue();
|
|
||||||
CompositeTransactionAttributeSource ctas = (CompositeTransactionAttributeSource) ti.getTransactionAttributeSource();
|
CompositeTransactionAttributeSource ctas = (CompositeTransactionAttributeSource) ti.getTransactionAttributeSource();
|
||||||
boolean condition1 = ctas.getTransactionAttributeSources()[0] instanceof NameMatchTransactionAttributeSource;
|
assertThat(ctas.getTransactionAttributeSources()[0] instanceof NameMatchTransactionAttributeSource).isTrue();
|
||||||
assertThat(condition1).isTrue();
|
assertThat(ctas.getTransactionAttributeSources()[1] instanceof NameMatchTransactionAttributeSource).isTrue();
|
||||||
boolean condition = ctas.getTransactionAttributeSources()[1] instanceof NameMatchTransactionAttributeSource;
|
|
||||||
assertThat(condition).isTrue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -132,7 +128,7 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
PlatformTransactionManager transactionManager = mock();
|
PlatformTransactionManager transactionManager = mock();
|
||||||
TransactionInterceptor ti = transactionInterceptorWithTransactionManager(transactionManager, null);
|
TransactionInterceptor ti = transactionInterceptorWithTransactionManager(transactionManager, null);
|
||||||
|
|
||||||
assertThat(ti.determineTransactionManager(new DefaultTransactionAttribute())).isSameAs(transactionManager);
|
assertThat(ti.determineTransactionManager(new DefaultTransactionAttribute(), null)).isSameAs(transactionManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -140,7 +136,7 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
PlatformTransactionManager transactionManager = mock();
|
PlatformTransactionManager transactionManager = mock();
|
||||||
TransactionInterceptor ti = transactionInterceptorWithTransactionManager(transactionManager, null);
|
TransactionInterceptor ti = transactionInterceptorWithTransactionManager(transactionManager, null);
|
||||||
|
|
||||||
assertThat(ti.determineTransactionManager(null)).isSameAs(transactionManager);
|
assertThat(ti.determineTransactionManager(null, null)).isSameAs(transactionManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -148,7 +144,7 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
BeanFactory beanFactory = mock();
|
BeanFactory beanFactory = mock();
|
||||||
TransactionInterceptor ti = simpleTransactionInterceptor(beanFactory);
|
TransactionInterceptor ti = simpleTransactionInterceptor(beanFactory);
|
||||||
|
|
||||||
assertThat(ti.determineTransactionManager(null)).isNull();
|
assertThat(ti.determineTransactionManager(null, null)).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -158,8 +154,8 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
||||||
attribute.setQualifier("fooTransactionManager");
|
attribute.setQualifier("fooTransactionManager");
|
||||||
|
|
||||||
assertThatExceptionOfType(NoSuchBeanDefinitionException.class).isThrownBy(() ->
|
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
|
||||||
ti.determineTransactionManager(attribute))
|
.isThrownBy(() -> ti.determineTransactionManager(attribute, null))
|
||||||
.withMessageContaining("'fooTransactionManager'");
|
.withMessageContaining("'fooTransactionManager'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +170,7 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
||||||
attribute.setQualifier("fooTransactionManager");
|
attribute.setQualifier("fooTransactionManager");
|
||||||
|
|
||||||
assertThat(ti.determineTransactionManager(attribute)).isSameAs(fooTransactionManager);
|
assertThat(ti.determineTransactionManager(attribute, null)).isSameAs(fooTransactionManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -189,7 +185,7 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
||||||
attribute.setQualifier("fooTransactionManager");
|
attribute.setQualifier("fooTransactionManager");
|
||||||
|
|
||||||
assertThat(ti.determineTransactionManager(attribute)).isSameAs(fooTransactionManager);
|
assertThat(ti.determineTransactionManager(attribute, null)).isSameAs(fooTransactionManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -203,7 +199,7 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
||||||
attribute.setQualifier("");
|
attribute.setQualifier("");
|
||||||
|
|
||||||
assertThat(ti.determineTransactionManager(attribute)).isSameAs(defaultTransactionManager);
|
assertThat(ti.determineTransactionManager(attribute, null)).isSameAs(defaultTransactionManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -215,11 +211,11 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
|
|
||||||
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
||||||
attribute.setQualifier("fooTransactionManager");
|
attribute.setQualifier("fooTransactionManager");
|
||||||
TransactionManager actual = ti.determineTransactionManager(attribute);
|
TransactionManager actual = ti.determineTransactionManager(attribute, null);
|
||||||
assertThat(actual).isSameAs(txManager);
|
assertThat(actual).isSameAs(txManager);
|
||||||
|
|
||||||
// Call again, should be cached
|
// Call again, should be cached
|
||||||
TransactionManager actual2 = ti.determineTransactionManager(attribute);
|
TransactionManager actual2 = ti.determineTransactionManager(attribute, null);
|
||||||
assertThat(actual2).isSameAs(txManager);
|
assertThat(actual2).isSameAs(txManager);
|
||||||
verify(beanFactory, times(1)).containsBean("fooTransactionManager");
|
verify(beanFactory, times(1)).containsBean("fooTransactionManager");
|
||||||
verify(beanFactory, times(1)).getBean("fooTransactionManager", TransactionManager.class);
|
verify(beanFactory, times(1)).getBean("fooTransactionManager", TransactionManager.class);
|
||||||
|
@ -234,11 +230,11 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
PlatformTransactionManager txManager = associateTransactionManager(beanFactory, "fooTransactionManager");
|
PlatformTransactionManager txManager = associateTransactionManager(beanFactory, "fooTransactionManager");
|
||||||
|
|
||||||
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
||||||
TransactionManager actual = ti.determineTransactionManager(attribute);
|
TransactionManager actual = ti.determineTransactionManager(attribute, null);
|
||||||
assertThat(actual).isSameAs(txManager);
|
assertThat(actual).isSameAs(txManager);
|
||||||
|
|
||||||
// Call again, should be cached
|
// Call again, should be cached
|
||||||
TransactionManager actual2 = ti.determineTransactionManager(attribute);
|
TransactionManager actual2 = ti.determineTransactionManager(attribute, null);
|
||||||
assertThat(actual2).isSameAs(txManager);
|
assertThat(actual2).isSameAs(txManager);
|
||||||
verify(beanFactory, times(1)).getBean("fooTransactionManager", TransactionManager.class);
|
verify(beanFactory, times(1)).getBean("fooTransactionManager", TransactionManager.class);
|
||||||
}
|
}
|
||||||
|
@ -252,11 +248,11 @@ class TransactionInterceptorTests extends AbstractTransactionAspectTests {
|
||||||
given(beanFactory.getBean(TransactionManager.class)).willReturn(txManager);
|
given(beanFactory.getBean(TransactionManager.class)).willReturn(txManager);
|
||||||
|
|
||||||
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
|
||||||
TransactionManager actual = ti.determineTransactionManager(attribute);
|
TransactionManager actual = ti.determineTransactionManager(attribute, null);
|
||||||
assertThat(actual).isSameAs(txManager);
|
assertThat(actual).isSameAs(txManager);
|
||||||
|
|
||||||
// Call again, should be cached
|
// Call again, should be cached
|
||||||
TransactionManager actual2 = ti.determineTransactionManager(attribute);
|
TransactionManager actual2 = ti.determineTransactionManager(attribute, null);
|
||||||
assertThat(actual2).isSameAs(txManager);
|
assertThat(actual2).isSameAs(txManager);
|
||||||
verify(beanFactory, times(1)).getBean(TransactionManager.class);
|
verify(beanFactory, times(1)).getBean(TransactionManager.class);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue