diff --git a/spring-aop/src/main/java/org/springframework/aop/support/ControlFlowPointcut.java b/spring-aop/src/main/java/org/springframework/aop/support/ControlFlowPointcut.java index 2b4242a3344..e04714ed792 100644 --- a/spring-aop/src/main/java/org/springframework/aop/support/ControlFlowPointcut.java +++ b/spring-aop/src/main/java/org/springframework/aop/support/ControlFlowPointcut.java @@ -151,8 +151,9 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher if (this.methodNamePatterns.isEmpty()) { return true; } - for (String methodNamePattern : this.methodNamePatterns) { - if (isMatch(element.getMethodName(), methodNamePattern)) { + String methodName = element.getMethodName(); + for (int i = 0; i < this.methodNamePatterns.size(); i++) { + if (isMatch(methodName, i)) { return true; } } @@ -179,8 +180,31 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher this.evaluationCount.incrementAndGet(); } + /** + * Determine if the given method name matches the method name pattern at the + * specified index. + *
This method is invoked by {@link #matches(Method, Class, Object...)}. + *
The default implementation retrieves the method name pattern from + * {@link #methodNamePatterns} and delegates to {@link #isMatch(String, String)}. + *
Can be overridden in subclasses — for example, to support + * regular expressions. + * @param methodName the method name to check + * @param patternIndex the index of the method name pattern + * @return {@code true} if the method name matches the pattern at the specified + * index + * @since 6.1 + * @see #methodNamePatterns + * @see #isMatch(String, String) + * @see #matches(Method, Class, Object...) + */ + protected boolean isMatch(String methodName, int patternIndex) { + String methodNamePattern = this.methodNamePatterns.get(patternIndex); + return isMatch(methodName, methodNamePattern); + } + /** * Determine if the given method name matches the method name pattern. + *
This method is invoked by {@link #isMatch(String, int)}. *
The default implementation checks for direct equality as well as * {@code xxx*}, {@code *xxx}, {@code *xxx*}, and {@code xxx*yyy} matches. *
Can be overridden in subclasses — for example, to support a
@@ -189,7 +213,7 @@ public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher
* @param methodNamePattern the method name pattern
* @return {@code true} if the method name matches the pattern
* @since 6.1
- * @see #matches(Method, Class, Object...)
+ * @see #isMatch(String, int)
* @see PatternMatchUtils#simpleMatch(String, String)
*/
protected boolean isMatch(String methodName, String methodNamePattern) {
diff --git a/spring-aop/src/test/java/org/springframework/aop/support/ControlFlowPointcutTests.java b/spring-aop/src/test/java/org/springframework/aop/support/ControlFlowPointcutTests.java
index 4165fe62a2c..3401b6fa18b 100644
--- a/spring-aop/src/test/java/org/springframework/aop/support/ControlFlowPointcutTests.java
+++ b/spring-aop/src/test/java/org/springframework/aop/support/ControlFlowPointcutTests.java
@@ -18,6 +18,7 @@ package org.springframework.aop.support;
import java.lang.reflect.Method;
import java.util.List;
+import java.util.regex.Pattern;
import org.junit.jupiter.api.Test;
@@ -73,6 +74,15 @@ class ControlFlowPointcutTests {
assertMatchesSetAndGetAge(cflow);
}
+ @Test
+ void regExControlFlowPointcut() {
+ ControlFlowPointcut cflow = new RegExControlFlowPointcut(MyComponent.class, "(set.*?|getAge)");
+ assertMatchesSetAndGetAge(cflow);
+
+ cflow = new RegExControlFlowPointcut(MyComponent.class, "set", "^getAge$");
+ assertMatchesSetAndGetAge(cflow);
+ }
+
@Test
void controlFlowPointcutIsExtensible() {
CustomControlFlowPointcut cflow = new CustomControlFlowPointcut(MyComponent.class, "set*", "getAge", "set*", "set*");
@@ -249,4 +259,20 @@ class ControlFlowPointcutTests {
}
}
+ @SuppressWarnings("serial")
+ private static class RegExControlFlowPointcut extends ControlFlowPointcut {
+
+ private final List