Spring AOP基础组件 Pointcut

相关阅读

简介

定义了切面的匹配点,即哪些类的哪些方法;在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();
    }
}

实现子类

Pointcut

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;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值