Skip to content

Commit 6df4b3f

Browse files
committed
feat: add global fallback support for AspectJ annotation extension (#3110)
Add SentinelAnnotationGlobalFallback interface and integrate it into AbstractSentinelAspectSupport as a last-resort fallback handler. When set on SentinelResourceAspect, the global fallback is invoked for all @SentinelResource-annotated methods when neither per-method fallback nor defaultFallback is configured (or found). This provides a universal 兜底 strategy without requiring each annotation to specify its own fallback. Changes: - New: SentinelAnnotationGlobalFallback interface with handle(Method, Object[], Throwable) contract - Modified: AbstractSentinelAspectSupport adds setGlobalFallback/getGlobalFallback - Modified: handleDefaultFallback() tries global fallback before throwing - Tests: 3 unit tests for get/set/clear global fallback Usage: SentinelResourceAspect aspect = new SentinelResourceAspect(); aspect.setGlobalFallback((method, args, t) -> { return "Global fallback: " + t.getMessage(); }); Fixes #3110
1 parent 872bbf8 commit 6df4b3f

3 files changed

Lines changed: 97 additions & 0 deletions

File tree

sentinel-extension/sentinel-annotation-aspectj/src/main/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupport.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,30 @@
3737
*/
3838
public abstract class AbstractSentinelAspectSupport {
3939

40+
/**
41+
* Global fallback handler, invoked as last resort when no per-method fallback
42+
* or default fallback is configured.
43+
*/
44+
private volatile SentinelAnnotationGlobalFallback globalFallback;
45+
46+
/**
47+
* Set the global fallback handler.
48+
*
49+
* @param globalFallback the global fallback handler (may be {@code null} to clear)
50+
*/
51+
public void setGlobalFallback(SentinelAnnotationGlobalFallback globalFallback) {
52+
this.globalFallback = globalFallback;
53+
}
54+
55+
/**
56+
* Get the current global fallback handler.
57+
*
58+
* @return the global fallback handler, or {@code null} if not set
59+
*/
60+
public SentinelAnnotationGlobalFallback getGlobalFallback() {
61+
return globalFallback;
62+
}
63+
4064
protected void traceException(Throwable ex) {
4165
Tracer.trace(ex);
4266
}
@@ -118,6 +142,12 @@ protected Object handleDefaultFallback(ProceedingJoinPoint pjp, String defaultFa
118142
return invoke(pjp, fallbackMethod, args);
119143
}
120144

145+
// If no default fallback is present, try the global fallback.
146+
if (globalFallback != null) {
147+
Method originMethod = resolveMethod(pjp);
148+
return globalFallback.handle(originMethod, pjp.getArgs(), ex);
149+
}
150+
121151
// If no any fallback is present, then directly throw the exception.
122152
throw ex;
123153
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 1999-2024 Alibaba Group Holding Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.alibaba.csp.sentinel.annotation.aspectj;
17+
18+
import java.lang.reflect.Method;
19+
20+
/**
21+
* Global fallback handler for {@link com.alibaba.csp.sentinel.annotation.SentinelResource} annotations.
22+
* <p>
23+
* When set on {@link SentinelResourceAspect}, this handler serves as the last-resort fallback
24+
* for all {@code @SentinelResource}-annotated methods, even when neither {@code fallback}
25+
* nor {@code defaultFallback} is specified in the annotation.
26+
* <p>
27+
* The global fallback is invoked only after both per-method fallback and default fallback
28+
* have been exhausted (i.e., not configured or not found).
29+
*
30+
* @author EvanYao826
31+
* @since 1.8.8
32+
*/
33+
public interface SentinelAnnotationGlobalFallback {
34+
35+
/**
36+
* Handle the fallback when a {@code @SentinelResource}-annotated method is blocked
37+
* or throws a traced exception.
38+
*
39+
* @param originalMethod the original annotated method
40+
* @param args the arguments passed to the original method
41+
* @param t the exception that triggered the fallback (may be a {@link
42+
* com.alibaba.csp.sentinel.slots.block.BlockException} or a traced business exception)
43+
* @return the fallback result
44+
* @throws Throwable if the fallback itself fails
45+
*/
46+
Object handle(Method originalMethod, Object[] args, Throwable t) throws Throwable;
47+
}

sentinel-extension/sentinel-annotation-aspectj/src/test/java/com/alibaba/csp/sentinel/annotation/aspectj/AbstractSentinelAspectSupportTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.lang.reflect.Method;
2222

2323
import static org.assertj.core.api.Assertions.*;
24+
import static org.mockito.Mockito.*;
2425

2526
/**
2627
* @author Eric Zhao
@@ -36,4 +37,23 @@ public void testGetResourceName() throws Exception {
3637
assertThat(getResourceName(null, method)).isEqualTo(expectedResolvedName);
3738
assertThat(getResourceName("", method)).isEqualTo(expectedResolvedName);
3839
}
40+
41+
@Test
42+
public void testGlobalFallbackDefaultIsNull() {
43+
assertThat(getGlobalFallback()).isNull();
44+
}
45+
46+
@Test
47+
public void testSetAndGetGlobalFallback() throws Throwable {
48+
SentinelAnnotationGlobalFallback fallback = mock(SentinelAnnotationGlobalFallback.class);
49+
setGlobalFallback(fallback);
50+
assertThat(getGlobalFallback()).isSameAs(fallback);
51+
}
52+
53+
@Test
54+
public void testClearGlobalFallback() {
55+
setGlobalFallback(mock(SentinelAnnotationGlobalFallback.class));
56+
setGlobalFallback(null);
57+
assertThat(getGlobalFallback()).isNull();
58+
}
3959
}

0 commit comments

Comments
 (0)