相关阅读
简介
定义了切面的匹配点,即哪些类的哪些方法;在Spring AOP中匹配点主要是class(ClassFilter
)和method(MethodFilter
)两个维度;
源码
Pointcut
public interface Pointcut {
// 类过滤器,用于匹配类
ClassFilter getClassFilter();
// 方法匹配器,用于匹配方法
MethodMatcher getMethodMatcher();
// 默认匹配所有类的所有方法
Pointcut TRUE = TruePointcut.INSTANCE;
}
TruePointcut
final class TruePointcut implements Pointcut, Serializable {
public static final TruePointcut INSTANCE = new TruePointcut();
/**
* Enforce Singleton pattern.
*/
private TruePointcut() {
}
// 匹配任何类
@Override
public ClassFilter getClassFilter() {
return ClassFilter.TRUE;
}
// 匹配任何方法
@Override
public MethodMatcher getMethodMatcher() {
return MethodMatcher.TRUE;
}
}
ClassFilter
@FunctionalInterface
public interface ClassFilter {
// 是否匹配指定的接口/类
boolean matches(Class<?> clazz);
// 匹配任意类型的示例
ClassFilter TRUE = TrueClassFilter.INSTANCE;
}
TrueClassFilter
final class TrueClassFilter implements ClassFilter, Serializable {
public static final TrueClassFilter INSTANCE = new TrueClassFilter();
// 确保单例
private TrueClassFilter() {
}
@Override
public boolean matches(Class<?> clazz) {
// 全匹配
return true;
}
}
MethodMatcher
public interface MethodMatcher {
// 是否静态地匹配指定类的指定方法
boolean matches(Method method, Class<?> targetClass);
// 是否动态匹配
boolean isRuntime();
// 是否动态地匹配指定类的指定方法
boolean matches(Method method, Class<?> targetClass, Object... args);
// 匹配任意方法的示例
MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}
TrueMethodMatcher
final class TrueMethodMatcher implements MethodMatcher, Serializable {
public static final TrueMethodMatcher INSTANCE = new TrueMethodMatcher();
// 确保单例
private TrueMethodMatcher() {
}
@Override
public boolean isRuntime() {
// 静态匹配
return false;
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 匹配任意类的任意方法
return true;
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
// 抛出不支持操作异常
throw new UnsupportedOperationException();
}
}
实现子类
ControlFlowPointcut
简介
根据在当前现成的堆栈信息中的方法名来决定是否切入某个方法;
核心代码
public class ControlFlowPointcut implements Pointcut, ClassFilter, MethodMatcher, Serializable {
// 匹配的类名,必须有效
private final Class<?> clazz;
// 匹配的方法名,支持为null,表示匹配任意方法
@Nullable
private final String methodName;
// 计数器
private final AtomicInteger evaluations = new AtomicInteger();
public ControlFlowPointcut(Class<?> clazz, @Nullable String methodName) {
// 校验类名的有效性
Assert.notNull(clazz, "Class must not be null");
this.clazz = clazz;
this.methodName = methodName;
}
@Override
public boolean matches(Class<?> clazz) {
// 匹配任意类
return true;
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 匹配任意类的任意方法
return true;
}
@Override
public boolean isRuntime() {
// 动态匹配
return true;
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
// 记录次数
this.evaluations.incrementAndGet();
// 遍历方法调用栈
for (StackTraceElement element : new Throwable().getStackTrace()) {
// 当前方法是否匹配类名和方法名
if (element.getClassName().equals(this.clazz.getName()) &&
(this.methodName == null || element.getMethodName().equals(this.methodName))) {
return true;
}
}
return false;
}
@Override
public ClassFilter getClassFilter() {
return this;
}
@Override
public MethodMatcher getMethodMatcher() {
return this;
}
}
ComposablePointcut
简介
组合模式的Pointcut
;
核心代码
public class ComposablePointcut implements Pointcut, Serializable {
private ClassFilter classFilter;
private MethodMatcher methodMatcher;
public ComposablePointcut() {
this.classFilter = ClassFilter.TRUE;
this.methodMatcher = MethodMatcher.TRUE;
}
public ComposablePointcut union(ClassFilter other) {
// 类过滤器并集
this.classFilter = ClassFilters.union(this.classFilter, other);
return this;
}
public ComposablePointcut intersection(ClassFilter other) {
// 类过滤器交集
this.classFilter = ClassFilters.intersection(this.classFilter, other);
return this;
}
public ComposablePointcut union(MethodMatcher other) {
// 方法匹配器并集
this.methodMatcher = MethodMatchers.union(this.methodMatcher, other);
return this;
}
public ComposablePointcut intersection(MethodMatcher other) {
// 方法匹配器交集
this.methodMatcher = MethodMatchers.intersection(this.methodMatcher, other);
return this;
}
public ComposablePointcut union(Pointcut other) {
// 方法匹配器并集
this.methodMatcher = MethodMatchers.union(
this.methodMatcher, this.classFilter, other.getMethodMatcher(), other.getClassFilter());
// 类过滤器并集
this.classFilter = ClassFilters.union(this.classFilter, other.getClassFilter());
return this;
}
public ComposablePointcut intersection(Pointcut other) {
// 类过滤器交集
this.classFilter = ClassFilters.intersection(this.classFilter, other.getClassFilter());
// 方法匹配器交集
this.methodMatcher = MethodMatchers.intersection(this.methodMatcher, other.getMethodMatcher());
return this;
}
@Override
public ClassFilter getClassFilter() {
return this.classFilter;
}
@Override
public MethodMatcher getMethodMatcher() {
return this.methodMatcher;
}
}
DynamicMethodMatcherPointcut
简介
动态匹配的Pointcut
;
核心代码
public abstract class DynamicMethodMatcherPointcut extends DynamicMethodMatcher implements Pointcut {
@Override
public ClassFilter getClassFilter() {
// 匹配任意类
return ClassFilter.TRUE;
}
@Override
public final MethodMatcher getMethodMatcher() {
return this;
}
}
DynamicMethodMatcher
public abstract class DynamicMethodMatcher implements MethodMatcher {
@Override
public final boolean isRuntime() {
// 动态匹配
return true;
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 静态匹配默认匹配
return true;
}
}
StaticMethodMatcherPointcut
简介
静态匹配的Pointcut
;
核心代码
public abstract class StaticMethodMatcherPointcut extends StaticMethodMatcher implements Pointcut {
// 类过滤器,默认匹配任意类
private ClassFilter classFilter = ClassFilter.TRUE;
public void setClassFilter(ClassFilter classFilter) {
// 设置类过滤器
this.classFilter = classFilter;
}
@Override
public ClassFilter getClassFilter() {
return this.classFilter;
}
@Override
public final MethodMatcher getMethodMatcher() {
return this;
}
}
StaticMethodMatcher
public abstract class StaticMethodMatcher implements MethodMatcher {
@Override
public final boolean isRuntime() {
// 静态匹配
return false;
}
@Override
public final boolean matches(Method method, Class<?> targetClass, Object... args) {
// 抛出不支持操作异常
throw new UnsupportedOperationException("Illegal MethodMatcher usage");
}
}
CacheOperationSourcePointcut
简介
Spring Cache
相关的Pointcut
;
核心代码
abstract class CacheOperationSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected CacheOperationSourcePointcut() {
// 设置类过滤器为CacheOperationSource类过滤器
setClassFilter(new CacheOperationSourceClassFilter());
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
CacheOperationSource cas = getCacheOperationSource();
// 指定方法上是否存在CacheOperation
return (cas != null && !CollectionUtils.isEmpty(cas.getCacheOperations(method, targetClass)));
}
// 获取CacheOperationSource,用于解析指定方法上的CacheOperation
@Nullable
protected abstract CacheOperationSource getCacheOperationSource();
// 根据CacheOperationSource.isCandidateClass实现的类过滤器
private class CacheOperationSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
if (CacheManager.class.isAssignableFrom(clazz)) {
// 不支持CacheManager
return false;
}
CacheOperationSource cas = getCacheOperationSource();
// CacheOperationSource不存在,或者CacheOperationSource支持该类
return (cas == null || cas.isCandidateClass(clazz));
}
}
}
TransactionAttributeSourcePointcut
简介
Spring事务相关的Pointcut
;
核心代码
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
// 设置类过滤器为TransactionAttributeSourceClassFilter
setClassFilter(new TransactionAttributeSourceClassFilter());
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
// 指定方法上是否存在TransactionAttribute
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
// 获取TransactionAttributeSourceClassFilter,用于解析指定方法上的TransactionAttribute
@Nullable
protected abstract TransactionAttributeSource getTransactionAttributeSource();
// 根据TransactionAttributeSource.isCandidateClass实现的类过滤器
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
TransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.isCandidateClass(clazz));
}
}
}
NameMatchMethodPointcut
简介
基于方法名称进行匹配的Pointcut
,支持通配符*
,如:xxx*
、*xxx
、*xxx*
;
核心代码
public class NameMatchMethodPointcut extends StaticMethodMatcherPointcut implements Serializable {
private List<String> mappedNames = new ArrayList<>();
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 遍历已配置的映射名称集合
for (String mappedName : this.mappedNames) {
if (mappedName.equals(method.getName()) || isMatch(method.getName(), mappedName)) {
// 指定的方法名称匹配上映射的名称则认为匹配
return true;
}
}
return false;
}
protected boolean isMatch(String methodName, String mappedName) {
// 判断指定的方法名称是否正则匹配映射名称,支持通配符*
return PatternMatchUtils.simpleMatch(mappedName, methodName);
}
}
AbstractRegexpMethodPointcut
简介
使用正则表达式匹配方法全限定名称的抽象基础类,定义了匹配算法骨架,由子类实现匹配算法细节;
核心代码
public abstract class AbstractRegexpMethodPointcut extends StaticMethodMatcherPointcut
implements Serializable {
// 匹配的正则表达式
private String[] patterns = new String[0];
// 排除的正则表达式
private String[] excludedPatterns = new String[0];
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 是否匹配方法的全限定名称
return (matchesPattern(ClassUtils.getQualifiedMethodName(method, targetClass)) ||
(targetClass != method.getDeclaringClass() &&
matchesPattern(ClassUtils.getQualifiedMethodName(method, method.getDeclaringClass()))));
}
protected boolean matchesPattern(String signatureString) {
// 遍历配置的匹配正则表达式
for (int i = 0; i < this.patterns.length; i++) {
boolean matched = matches(signatureString, i);
if (matched) {
// 如果匹配上,则继续判断是否匹配排除正则表达式
for (int j = 0; j < this.excludedPatterns.length; j++) {
boolean excluded = matchesExclusion(signatureString, j);
if (excluded) {
// 如果匹配上排除正则表达式,则认为不匹配
return false;
}
}
// 未匹配上任何排除正则表达式,则认为匹配
return true;
}
}
// 未匹配上任何匹配正则表达式,则认为未匹配
return false;
}
// 初始化匹配正则表达式
protected abstract void initPatternRepresentation(String[] patterns) throws IllegalArgumentException;
// 初始化排除正则表达式
protected abstract void initExcludedPatternRepresentation(String[] patterns) throws IllegalArgumentException;
// 是否匹配指定匹配正则
protected abstract boolean matches(String pattern, int patternIndex);
// 是否匹配指定排除正则
protected abstract boolean matchesExclusion(String pattern, int patternIndex);
}
JdkRegexpMethodPointcut
简介
基于java.util.regex
实现的正则表达式Pointcut
;
核心代码
public class JdkRegexpMethodPointcut extends AbstractRegexpMethodPointcut {
// 匹配正则
private Pattern[] compiledPatterns = new Pattern[0];
// 排除正则
private Pattern[] compiledExclusionPatterns = new Pattern[0];
// 初始化匹配正则表达式
@Override
protected void initPatternRepresentation(String[] patterns) throws PatternSyntaxException {
this.compiledPatterns = compilePatterns(patterns);
}
// 初始化排除正则表达式
@Override
protected void initExcludedPatternRepresentation(String[] excludedPatterns) throws PatternSyntaxException {
this.compiledExclusionPatterns = compilePatterns(excludedPatterns);
}
// 是否匹配匹配正则
@Override
protected boolean matches(String pattern, int patternIndex) {
Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);
return matcher.matches();
}
// 是否匹配排除正则
@Override
protected boolean matchesExclusion(String candidate, int patternIndex) {
Matcher matcher = this.compiledExclusionPatterns[patternIndex].matcher(candidate);
return matcher.matches();
}
// 编译正则表达式
private Pattern[] compilePatterns(String[] source) throws PatternSyntaxException {
Pattern[] destination = new Pattern[source.length];
for (int i = 0; i < source.length; i++) {
destination[i] = Pattern.compile(source[i]);
}
return destination;
}
}
AnnotationMatchingPointcut
简介
匹配类上或者方法上是否有指定注解的Pointcut
;
核心代码
public class AnnotationMatchingPointcut implements Pointcut {
private final ClassFilter classFilter;
private final MethodMatcher methodMatcher;
public AnnotationMatchingPointcut(Class<? extends Annotation> classAnnotationType, boolean checkInherited) {
// AnnotationClassFilter类过滤器,checkInherited决定要不要寻找classAnnotationType的超类
this.classFilter = new AnnotationClassFilter(classAnnotationType, checkInherited);
// 匹配任意方法
this.methodMatcher = MethodMatcher.TRUE;
}
public AnnotationMatchingPointcut(@Nullable Class<? extends Annotation> classAnnotationType,
@Nullable Class<? extends Annotation> methodAnnotationType, boolean checkInherited) {
Assert.isTrue((classAnnotationType != null || methodAnnotationType != null),
"Either Class annotation type or Method annotation type needs to be specified (or both)");
// 设置类过滤器
if (classAnnotationType != null) {
this.classFilter = new AnnotationClassFilter(classAnnotationType, checkInherited);
}
else {
this.classFilter = new AnnotationCandidateClassFilter(methodAnnotationType);
}
// 设置方法过滤器
if (methodAnnotationType != null) {
this.methodMatcher = new AnnotationMethodMatcher(methodAnnotationType, checkInherited);
}
else {
this.methodMatcher = MethodMatcher.TRUE;
}
}
@Override
public ClassFilter getClassFilter() {
return this.classFilter;
}
@Override
public MethodMatcher getMethodMatcher() {
return this.methodMatcher;
}
// 生成匹配类上特定注解类型的AnnotationMatchingPointcut的工厂方法
public static AnnotationMatchingPointcut forClassAnnotation(Class<? extends Annotation> annotationType) {
Assert.notNull(annotationType, "Annotation type must not be null");
return new AnnotationMatchingPointcut(annotationType);
}
// 生成匹配方法上特定注解类型的AnnotationMatchingPointcut的工厂方法
public static AnnotationMatchingPointcut forMethodAnnotation(Class<? extends Annotation> annotationType) {
Assert.notNull(annotationType, "Annotation type must not be null");
return new AnnotationMatchingPointcut(null, annotationType);
}
// 注解候选类过滤器,用于过滤那些无需搜索其方法的类型
private static class AnnotationCandidateClassFilter implements ClassFilter {
private final Class<? extends Annotation> annotationType;
AnnotationCandidateClassFilter(Class<? extends Annotation> annotationType) {
this.annotationType = annotationType;
}
@Override
public boolean matches(Class<?> clazz) {
// 该clazz是否可以携带this.annotationType
return AnnotationUtils.isCandidateClass(clazz, this.annotationType);
}
}
}
AspectJExpressionPointcut
简介
Spring中使用AspectJ
编织器来评估切点表达式的Pointcut
实现;
切入点表达式值是一个 AspectJ 表达式,这可以引用其他切点,可以使用组合和其他操作。
由于这是由Spring AOP基于代理模型实现的,因此只支持方法执行切点;
核心方法
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
@Override
public ClassFilter getClassFilter() {
obtainPointcutExpression();
return this;
}
@Override
public MethodMatcher getMethodMatcher() {
obtainPointcutExpression();
return this;
}
private PointcutExpression obtainPointcutExpression() {
// 校验expression
if (getExpression() == null) {
throw new IllegalStateException("Must set property 'expression' before attempting to match");
}
// this.pointcutExpression懒构建
if (this.pointcutExpression == null) {
this.pointcutClassLoader = determinePointcutClassLoader();
// 构建this.pointcutExpression
this.pointcutExpression = buildPointcutExpression(this.pointcutClassLoader);
}
return this.pointcutExpression;
}
// 将and/or/not转换为AspectJ逻辑运算符
private String replaceBooleanOperators(String pcExpr) {
String result = StringUtils.replace(pcExpr, " and ", " && ");
result = StringUtils.replace(result, " or ", " || ");
result = StringUtils.replace(result, " not ", " ! ");
return result;
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
return matches(method, targetClass, false);
}
@Override
public boolean isRuntime() {
return obtainPointcutExpression().mayNeedDynamicTest();
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
obtainPointcutExpression();
ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
ProxyMethodInvocation pmi = null;
Object targetObject = null;
Object thisObject = null;
try {
MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
targetObject = mi.getThis();
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
pmi = (ProxyMethodInvocation) mi;
thisObject = pmi.getProxy();
}
catch (IllegalStateException ex) {
// log
}
try {
JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
if (pmi != null && thisObject != null) { // there is a current invocation
RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(getShadowMatch(method, method));
if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
return false;
}
if (joinPointMatch.matches()) {
bindParameters(pmi, joinPointMatch);
}
}
return joinPointMatch.matches();
}
catch (Throwable ex) {
// log
return false;
}
}
}