Subclasses are responsible for calling methods in this class in the correct order.
*
- *
If no transaction name has been specified in the {@code TransactionAttribute},
+ *
If no transaction name has been specified in the {@link TransactionAttribute},
* the exposed name will be the {@code fully-qualified class name + "." + method name}
* (by default).
*
- *
Uses the Strategy design pattern. A {@code PlatformTransactionManager}
- * implementation will perform the actual transaction management, and a
- * {@code TransactionAttributeSource} is used for determining transaction definitions.
+ *
Uses the Strategy design pattern. A {@link PlatformTransactionManager} or
+ * {@link ReactiveTransactionManager} implementation will perform the actual transaction
+ * management, and a {@link TransactionAttributeSource} (e.g. annotation-based) is used
+ * for determining transaction definitions for a particular class or method.
*
*
A transaction aspect is serializable if its {@code PlatformTransactionManager}
* and {@code TransactionAttributeSource} are serializable.
@@ -72,7 +73,10 @@ import org.springframework.util.StringUtils;
* @author Juergen Hoeller
* @author Stéphane Nicoll
* @author Sam Brannen
+ * @author Mark Paluch
* @since 1.1
+ * @see PlatformTransactionManager
+ * @see ReactiveTransactionManager
* @see #setTransactionManager
* @see #setTransactionAttributes
* @see #setTransactionAttributeSource
@@ -450,7 +454,8 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
else {
PlatformTransactionManager defaultTransactionManager = asPlatformTransactionManager(getTransactionManager());
if (defaultTransactionManager == null) {
- defaultTransactionManager = asPlatformTransactionManager(this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY));
+ defaultTransactionManager = asPlatformTransactionManager(
+ this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY));
if (defaultTransactionManager == null) {
defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
this.transactionManagerCache.putIfAbsent(
@@ -817,7 +822,6 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
this.adapter = adapter;
}
- @SuppressWarnings({ "unchecked", "rawtypes" })
public Object invokeWithinTransaction(Method method, @Nullable Class> targetClass, InvocationCallback invocation) {
// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas = getTransactionAttributeSource();
@@ -827,62 +831,53 @@ public abstract class TransactionAspectSupport implements BeanFactoryAware, Init
// Optimize for Mono
if (Mono.class.isAssignableFrom(method.getReturnType())) {
- return TransactionContextManager.currentContext().flatMap(context -> {
- // Standard transaction demarcation with getTransaction and commit/rollback calls.
- Mono txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
- return txInfo.flatMap(it -> {
+ return TransactionContextManager.currentContext().flatMap(context ->
+ createTransactionIfNecessary(tm, txAttr, joinpointIdentification).flatMap(it -> {
+ try {
+ // This is an around advice: Invoke the next interceptor in the chain.
+ // This will normally result in a target object being invoked.
+ // Need re-wrapping of ReactiveTransaction until we get hold of the exception
+ // through usingWhen.
+ return Mono.