Introduce configurable default rollback rules

Includes rollbackOn annotation attribute on @EnableTransactionManagement and addDefaultRollbackRule method on AnnotationTransactionAttributeSource, as well as publicMethodsOnly as instance-level flag (also on AnnotationCacheOperationSource).

Closes gh-23473
This commit is contained in:
Juergen Hoeller
2024-03-05 18:08:08 +01:00
parent eb01cc0d9d
commit 7d4c8a403e
12 changed files with 295 additions and 71 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 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.
@@ -19,10 +19,8 @@ package org.springframework.cache.annotation;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.cache.interceptor.AbstractFallbackCacheOperationSource;
@@ -47,17 +45,17 @@ import org.springframework.util.Assert;
@SuppressWarnings("serial")
public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperationSource implements Serializable {
private final boolean publicMethodsOnly;
private final Set<CacheAnnotationParser> annotationParsers;
private boolean publicMethodsOnly = true;
/**
* Create a default AnnotationCacheOperationSource, supporting public methods
* that carry the {@code Cacheable} and {@code CacheEvict} annotations.
*/
public AnnotationCacheOperationSource() {
this(true);
this.annotationParsers = Collections.singleton(new SpringCacheAnnotationParser());
}
/**
@@ -66,10 +64,11 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati
* @param publicMethodsOnly whether to support only annotated public methods
* typically for use with proxy-based AOP), or protected/private methods as well
* (typically used with AspectJ class weaving)
* @see #setPublicMethodsOnly
*/
public AnnotationCacheOperationSource(boolean publicMethodsOnly) {
this();
this.publicMethodsOnly = publicMethodsOnly;
this.annotationParsers = Collections.singleton(new SpringCacheAnnotationParser());
}
/**
@@ -77,7 +76,6 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati
* @param annotationParser the CacheAnnotationParser to use
*/
public AnnotationCacheOperationSource(CacheAnnotationParser annotationParser) {
this.publicMethodsOnly = true;
Assert.notNull(annotationParser, "CacheAnnotationParser must not be null");
this.annotationParsers = Collections.singleton(annotationParser);
}
@@ -87,9 +85,8 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati
* @param annotationParsers the CacheAnnotationParser to use
*/
public AnnotationCacheOperationSource(CacheAnnotationParser... annotationParsers) {
this.publicMethodsOnly = true;
Assert.notEmpty(annotationParsers, "At least one CacheAnnotationParser needs to be specified");
this.annotationParsers = new LinkedHashSet<>(Arrays.asList(annotationParsers));
this.annotationParsers = Set.of(annotationParsers);
}
/**
@@ -97,12 +94,21 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati
* @param annotationParsers the CacheAnnotationParser to use
*/
public AnnotationCacheOperationSource(Set<CacheAnnotationParser> annotationParsers) {
this.publicMethodsOnly = true;
Assert.notEmpty(annotationParsers, "At least one CacheAnnotationParser needs to be specified");
this.annotationParsers = annotationParsers;
}
/**
* Set whether cacheable methods are expected to be public.
* <p>The default is {@code true}.
* @since 6.2
*/
public void setPublicMethodsOnly(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
}
@Override
public boolean isCandidateClass(Class<?> targetClass) {
for (CacheAnnotationParser parser : this.annotationParsers) {
@@ -156,6 +162,7 @@ public class AnnotationCacheOperationSource extends AbstractFallbackCacheOperati
/**
* By default, only public methods can be made cacheable.
* @see #setPublicMethodsOnly
*/
@Override
protected boolean allowPublicMethodsOnly() {