Ensure it's possible to extend ControlFlowPointcut with RegEx support

Commit d3fba6d49b introduced built-in pattern matching support for
method names in ControlFlowPointcut; however, it was still cumbersome
to extend ControlFlowPointcut with support for regular expressions
instead of simple pattern matching.

To address that, this commit introduces a variant of isMatch() that
accepts the pattern index instead of the pre-resolved method name
pattern. The default implementation retrieves the method name pattern
from the methodNamePatterns field and delegates to isMatch(String, String).

Subclasses can override the new isMatch(String, int) method to support
regular expressions, as can be seen in the example
RegExControlFlowPointcut class in ControlFlowPointcutTests.

See gh-31435
This commit is contained in:
Sam Brannen
2023-10-28 15:53:20 +02:00
parent 7f1beb0140
commit c7bb981db1
2 changed files with 53 additions and 3 deletions

View File

@@ -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<Pattern> compiledPatterns;
RegExControlFlowPointcut(Class<?> clazz, String... methodNamePatterns) {
super(clazz, methodNamePatterns);
this.compiledPatterns = super.methodNamePatterns.stream().map(Pattern::compile).toList();
}
@Override
protected boolean isMatch(String methodName, int patternIndex) {
return this.compiledPatterns.get(patternIndex).matcher(methodName).matches();
}
}
}