@Aspect 注解切面解析

注解切面解析

  • 注解切面解析器
/**
 *  注解切面解析器
 */
public class BeanFactoryAspectJAdvisorsBuilder {
    /**
     *  Bean 工厂
     */
    private final ListableBeanFactory beanFactory;
    /**
     *  生成 Advisor 的工厂
     */
    private final AspectJAdvisorFactory advisorFactory;
    /**
     *  切面 Bean 名称
     */
    @Nullable
    private volatile List<String> aspectBeanNames;
    /**
     *  通知者缓存
     */
    private final Map<String, List<Advisor>> advisorsCache = new ConcurrentHashMap<>();
    /**
     *  切面实例缓存
     */
    private final Map<String, MetadataAwareAspectInstanceFactory> aspectFactoryCache = new ConcurrentHashMap<>();

    public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory) {
        this(beanFactory, new ReflectiveAspectJAdvisorFactory(beanFactory));
    }

    public BeanFactoryAspectJAdvisorsBuilder(ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
        Assert.notNull(beanFactory, "ListableBeanFactory must not be null");
        Assert.notNull(advisorFactory, "AspectJAdvisorFactory must not be null");
        this.beanFactory = beanFactory;
        this.advisorFactory = advisorFactory;
    }

    public List<Advisor> buildAspectJAdvisors() {
        List<String> aspectNames = aspectBeanNames;
        if (aspectNames == null) {
            synchronized (this) {
                aspectNames = aspectBeanNames;
                if (aspectNames == null) {
                    final List<Advisor> advisors = new ArrayList<>();
                    aspectNames = new ArrayList<>();
                    // 读取容器中所有的类
                    final String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                            beanFactory, Object.class, true, false);
                    for (final String beanName : beanNames) {
                        if (!isEligibleBean(beanName)) {
                            continue;
                        }

                        // 读取 Bean 的类型,不能执行初始化操作
                        final Class<?> beanType = beanFactory.getType(beanName);
                        if (beanType == null) {
                            continue;
                        }

                        // 指定的 bean 是否是一个注解切面
                        if (advisorFactory.isAspect(beanType)) {
                            aspectNames.add(beanName);
                            // 创建切面元数据
                            final AspectMetadata amd = new AspectMetadata(beanType, beanName);
                            // 切面是否是单例
                            if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                                final MetadataAwareAspectInstanceFactory factory =
                                        new BeanFactoryAspectInstanceFactory(beanFactory, beanName);
                                // 基于目标切面创建相关的 Advisor
                                final List<Advisor> classAdvisors = advisorFactory.getAdvisors(factory);
                                // 切面 bean 是单例 && 将通知者加入缓存
                                if (beanFactory.isSingleton(beanName)) {
                                    advisorsCache.put(beanName, classAdvisors);
                                }
                                else {
                                    aspectFactoryCache.put(beanName, factory);
                                }
                                advisors.addAll(classAdvisors);
                            }
                            else {
                                // Per target or per this.
                                if (beanFactory.isSingleton(beanName)) {
                                    throw new IllegalArgumentException("Bean with name '" + beanName +
                                            "' is a singleton, but aspect instantiation model is not singleton");
                                }
                                final MetadataAwareAspectInstanceFactory factory =
                                        new PrototypeAspectInstanceFactory(beanFactory, beanName);
                                aspectFactoryCache.put(beanName, factory);
                                advisors.addAll(advisorFactory.getAdvisors(factory));
                            }
                        }
                    }
                    aspectBeanNames = aspectNames;
                    return advisors;
                }
            }
        }

        // 无注解切面
        if (aspectNames.isEmpty()) {
            return Collections.emptyList();
        }
        final List<Advisor> advisors = new ArrayList<>();
        for (final String aspectName : aspectNames) {
            // 获取指定注解切面的所有 Advisor
            final List<Advisor> cachedAdvisors = advisorsCache.get(aspectName);
            if (cachedAdvisors != null) {
                advisors.addAll(cachedAdvisors);
            }
            else {
                final MetadataAwareAspectInstanceFactory factory = aspectFactoryCache.get(aspectName);
                advisors.addAll(advisorFactory.getAdvisors(factory));
            }
        }
        return advisors;
    }

    /**
     * 指定 bean 名称的切面是否合格
     */
    protected boolean isEligibleBean(String beanName) {
        return true;
    }
}
  • 通知者创建工厂
/**
 *  基于标注了 AspectJ 注解的类创建 Spring AOP 通知者
 */
public interface AspectJAdvisorFactory {

    /**
     *  指定类型是否是一个切面
     */
    boolean isAspect(Class<?> clazz);

    /**
     *  指定类型是否是一个有效的 AspectJ 切面类
     */
    void validate(Class<?> aspectClass) throws AopConfigException;

    /**
     *  将所有标注了 AspectJ 注解的方法转换为 Advisor
     */
    List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory);

    /**
     *  为给定的AspectJ通知方法构建一个Spring AOP通知
     */
    @Nullable
    Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrder, String aspectName);

    /**
     *  为给定的AspectJ通知方法构建一个Spring AOP通知
     *
     * @param candidateAdviceMethod 候选通知方法
     * @param expressionPointcut    AspectJ 切点表达式
     * @param aspectInstanceFactory Aspect 实例工厂
     * @param declarationOrder  通知方法在切面中的声明顺序
     * @param aspectName    切面的名称
     * @return {@code null} 非通知方法和切点都返回 null
     *
     * @see org.springframework.aop.aspectj.AspectJAroundAdvice 环绕通知
     * @see org.springframework.aop.aspectj.AspectJMethodBeforeAdvice   前置通知
     * @see org.springframework.aop.aspectj.AspectJAfterAdvice  后置通知
     * @see org.springframework.aop.aspectj.AspectJAfterReturningAdvice 正常返回通知
     * @see org.springframework.aop.aspectj.AspectJAfterThrowingAdvice  异常通知
     */
    @Nullable
    Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName);
}

public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFactory {
    private static final String AJC_MAGIC = "ajc$";
    /**
     *  AspectJ 注解类型
     */
    private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
        Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};

        /** Logger available to subclasses. */
        protected final Log logger = LogFactory.getLog(getClass());

        protected final ParameterNameDiscoverer parameterNameDiscoverer = new AspectJAnnotationParameterNameDiscoverer();


        /**
         *  目标类型是否是一个注解切面【目标类型上存在 @Aspect 注解并且不是由 ajc 编译】
         */
        @Override
        public boolean isAspect(Class<?> clazz) {
            return hasAspectAnnotation(clazz) && !compiledByAjc(clazz);
        }

        /**
         *  目标类型上是否有 Aspect 注解【如果没有直接标注,则尝试递归查找父类及其类型上的注解、实现的接口及其类型上的注解】
         */
        private boolean hasAspectAnnotation(Class<?> clazz) {
            return AnnotationUtils.findAnnotation(clazz, Aspect.class) != null;
        }

        private boolean compiledByAjc(Class<?> clazz) {
            for (final Field field : clazz.getDeclaredFields()) {
                // 方法名称由 ajc$ 开头
                if (field.getName().startsWith(AJC_MAGIC)) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public void validate(Class<?> aspectClass) throws AopConfigException {
            // 如果父类有注解而不是抽象类,那就是一个错误
            if (aspectClass.getSuperclass().getAnnotation(Aspect.class) != null &&
                    !Modifier.isAbstract(aspectClass.getSuperclass().getModifiers())) {
                throw new AopConfigException("[" + aspectClass.getName() + "] cannot extend concrete aspect [" +
                        aspectClass.getSuperclass().getName() + "]");
            }

            final AjType<?> ajType = AjTypeSystem.getAjType(aspectClass);
            if (!ajType.isAspect()) {
                throw new NotAnAtAspectException(aspectClass);
            }
            if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOW) {
                throw new AopConfigException(aspectClass.getName() + " uses percflow instantiation model: " +
                        "This is not supported in Spring AOP.");
            }
            if (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOWBELOW) {
                throw new AopConfigException(aspectClass.getName() + " uses percflowbelow instantiation model: " +
                        "This is not supported in Spring AOP.");
            }
        }

        /**
         *  查找并返回给定方法上的第一个 AspectJ注释。
         *  查找顺序:Pointcut.class, Around.class, Before.class,
         *  After.class, AfterReturning.class, AfterThrowing.class
         */
        @SuppressWarnings("unchecked")
        @Nullable
        protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
            for (final Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
                final AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
                if (foundAnnotation != null) {
                    return foundAnnotation;
                }
            }
            return null;
        }

        @Nullable
        private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
            final A result = AnnotationUtils.findAnnotation(method, toLookFor);
            if (result != null) {
                return new AspectJAnnotation<>(result);
            }
            else {
                return null;
            }
        }

        /**
         *  AspectJ 注解类型枚举
         */
        protected enum AspectJAnnotationType {
            AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
        }


        /**
         *  对一个 AspectJ 注解进行建模,公开其类型枚举和切点字符串
         */
        protected static class AspectJAnnotation<A extends Annotation> {
            private static final String[] EXPRESSION_ATTRIBUTES = new String[] {"pointcut", "value"};
            private static Map<Class<?>, AspectJAnnotationType> annotationTypeMap = new HashMap<>(8);

            static {
                annotationTypeMap.put(Pointcut.class, AspectJAnnotationType.AtPointcut);
                annotationTypeMap.put(Around.class, AspectJAnnotationType.AtAround);
                annotationTypeMap.put(Before.class, AspectJAnnotationType.AtBefore);
                annotationTypeMap.put(After.class, AspectJAnnotationType.AtAfter);
                annotationTypeMap.put(AfterReturning.class, AspectJAnnotationType.AtAfterReturning);
                annotationTypeMap.put(AfterThrowing.class, AspectJAnnotationType.AtAfterThrowing);
            }

            /**
             *  目标注解
             */
            private final A annotation;
            /**
             *  AspectJ 注解类型枚举
             */
            private final AspectJAnnotationType annotationType;
            /**
             *  切点字符串
             */
            private final String pointcutExpression;
            /**
             *  参数名称
             */
            private final String argumentNames;

            public AspectJAnnotation(A annotation) {
                this.annotation = annotation;
                this.annotationType = determineAnnotationType(annotation);
                try {
                    this.pointcutExpression = resolveExpression(annotation);
                    final Object argNames = AnnotationUtils.getValue(annotation, "argNames");
                    this.argumentNames = argNames instanceof String ? (String) argNames : "";
                }
                catch (final Exception ex) {
                    throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
                }
            }

            private AspectJAnnotationType determineAnnotationType(A annotation) {
                final AspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());
                if (type != null) {
                    return type;
                }
                throw new IllegalStateException("Unknown annotation type: " + annotation);
            }

            private String resolveExpression(A annotation) {
                // "pointcut", "value"
                for (final String attributeName : EXPRESSION_ATTRIBUTES) {
                    final Object val = AnnotationUtils.getValue(annotation, attributeName);
                    if (val instanceof String) {
                        final String str = (String) val;
                        if (!str.isEmpty()) {
                            return str;
                        }
                    }
                }
                throw new IllegalStateException("Failed to resolve expression: " + annotation);
            }

            public AspectJAnnotationType getAnnotationType() {
                return this.annotationType;
            }

            public A getAnnotation() {
                return this.annotation;
            }

            public String getPointcutExpression() {
                return this.pointcutExpression;
            }

            public String getArgumentNames() {
                return this.argumentNames;
            }

            @Override
            public String toString() {
                return this.annotation.toString();
            }
        }


        /**
         *  解析在 AspectJ 注解级别定义的参数
         */
        private static class AspectJAnnotationParameterNameDiscoverer implements ParameterNameDiscoverer {

            @Override
            @Nullable
            public String[] getParameterNames(Method method) {
                if (method.getParameterCount() == 0) {
                    return new String[0];
                }
                // 读取目标方法上的 AspectJ 注解
                final AspectJAnnotation<?> annotation = findAspectJAnnotationOnMethod(method);
                if (annotation == null) {
                    return null;
                }
                final StringTokenizer nameTokens = new StringTokenizer(annotation.getArgumentNames(), ",");
                if (nameTokens.countTokens() > 0) {
                    final String[] names = new String[nameTokens.countTokens()];
                    for (int i = 0; i < names.length; i++) {
                        names[i] = nameTokens.nextToken();
                    }
                    return names;
                }
                else {
                    return null;
                }
            }

            @Override
            @Nullable
            public String[] getParameterNames(Constructor<?> ctor) {
                throw new UnsupportedOperationException("Spring AOP cannot handle constructor advice");
            }
        }
}

/**
 *  通过反射来执行 AspectJ 注解关联的通知方法的 AdvisorFactory
 */
@SuppressWarnings("serial")
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
    private static final Comparator<Method> METHOD_COMPARATOR;

    static {
        final Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
                // 根据声明的类型顺序进行排序
                new InstanceComparator<>(
                        Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
                (Converter<Method, Annotation>) method -> {
                    final AspectJAnnotation<?> annotation =
                            AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
                    return annotation != null ? annotation.getAnnotation() : null;
                });
        final Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
        METHOD_COMPARATOR = adviceKindComparator.thenComparing(methodNameComparator);
    }

    @Nullable
    private final BeanFactory beanFactory;

    public ReflectiveAspectJAdvisorFactory() {
        this(null);
    }

    public ReflectiveAspectJAdvisorFactory(@Nullable BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    @Override
    public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
        // 读取切面类型
        final Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        // 读取切面名称
        final String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
        // 验证切面类
        validate(aspectClass);

        // 只实例化切面一次的装饰器
        final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
                new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
        final List<Advisor> advisors = new ArrayList<>();
        // 读取除切点外的所有方法
        for (final Method method : getAdvisorMethods(aspectClass)) {
            // 尝试从目标方法上构建 Advisor,创建 InstantiationModelAwarePointcutAdvisorImpl 时即初始化
            final Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }

        // If it's a per target aspect, emit the dummy instantiating aspect.
        if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
            final Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
            advisors.add(0, instantiationAdvisor);
        }

        // 是否需要动态地为指定的类型增加方法:读取当前切面中定义的所有字段
        for (final Field field : aspectClass.getDeclaredFields()) {
            final Advisor advisor = getDeclareParentsAdvisor(field);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }

        return advisors;
    }

    private List<Method> getAdvisorMethods(Class<?> aspectClass) {
        final List<Method> methods = new ArrayList<>();
        ReflectionUtils.doWithMethods(aspectClass, method -> {
            // 排除切点方法
            if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                methods.add(method);
            }
        });
        // 排序
        methods.sort(METHOD_COMPARATOR);
        return methods;
    }

    /**
     *  尝试为指定的类型新增方法
     */
    @Nullable
    private Advisor getDeclareParentsAdvisor(Field introductionField) {
        // 1)目标属性上存在 DeclareParents 注解
        final DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
        if (declareParents == null) {
            return null;
        }

        // 2)指定了增强实现
        if (DeclareParents.class == declareParents.defaultImpl()) {
            throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
        }

        return new DeclareParentsAdvisor(
                introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
    }


    @Override
    @Nullable
    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {
        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        // 读取切点表达式
        final AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        if (expressionPointcut == null) {
            return null;
        }

        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

    @Nullable
    private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
        /**
         *  查找并返回给定方法上的第一个 AspectJ 注释。
         *  查找顺序:Pointcut.class, Around.class, Before.class,
         *  After.class, AfterReturning.class, AfterThrowing.class
         */
        final AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }

        // 创建 AspectJ 表达式切点
        final AspectJExpressionPointcut ajexp =
                new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
        ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
        if (beanFactory != null) {
            ajexp.setBeanFactory(beanFactory);
        }
        return ajexp;
    }


    @Override
    @Nullable
    public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
        final Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        validate(candidateAspectClass);

        final AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }

        // If we get here, we know we have an AspectJ method. Check that it's an AspectJ-annotated class
        if (!isAspect(candidateAspectClass)) {
            throw new AopConfigException("Advice must be declared inside an aspect type: " +
                    "Offending method '" + candidateAdviceMethod + "' in class [" +
                    candidateAspectClass.getName() + "]");
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Found AspectJ method: " + candidateAdviceMethod);
        }

        AbstractAspectJAdvice springAdvice;
        switch (aspectJAnnotation.getAnnotationType()) {
            // 切点
            case AtPointcut:
                if (logger.isDebugEnabled()) {
                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }
                return null;
                // 环绕通知
            case AtAround:
                springAdvice = new AspectJAroundAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
                // 前置通知
            case AtBefore:
                springAdvice = new AspectJMethodBeforeAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
                // 后置通知
            case AtAfter:
                springAdvice = new AspectJAfterAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
                // 正常返回通知
            case AtAfterReturning:
                springAdvice = new AspectJAfterReturningAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                // 如果 AfterReturning 通知将方法返回结果绑定了命名参数
                final AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                    springAdvice.setReturningName(afterReturningAnnotation.returning());
                }
                break;
                // 异常通知
            case AtAfterThrowing:
                springAdvice = new AspectJAfterThrowingAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                // 如果 AfterThrowing 通知将方法抛出的异常绑定了命名参数
                final AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                    springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
                }
                break;
            default:
                throw new UnsupportedOperationException(
                        "Unsupported advice type on method: " + candidateAdviceMethod);
        }

        // 配置 Advice
        springAdvice.setAspectName(aspectName);
        // 声明顺序
        springAdvice.setDeclarationOrder(declarationOrder);
        // 解析参数名称
        final String[] argNames = parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
        if (argNames != null) {
            springAdvice.setArgumentNamesFromStringArray(argNames);
        }
        // 计算参数绑定
        springAdvice.calculateArgumentBindings();

        return springAdvice;
    }


    /**
     *  实例化此切面的合成通知则
     */
    @SuppressWarnings("serial")
    protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
        public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
            super(aif.getAspectMetadata().getPerClausePointcut(), (MethodBeforeAdvice)
                    (method, args, target) -> aif.getAspectInstance());
        }
    }
}
  • 通知分类
/**
 *  封装 AspectJ 切面或 AspectJ 注解的通知方法
 */
@SuppressWarnings("serial")
public abstract class AbstractAspectJAdvice implements Advice, AspectJPrecedenceInformation, Serializable {
    /**
     * Key used in ReflectiveMethodInvocation userAttributes map for the current joinpoint.
     */
    protected static final String JOIN_POINT_KEY = JoinPoint.class.getName();


    /**
     *  延迟初始化当前调用的连接点
     */
    public static JoinPoint currentJoinPoint() {
        final MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
        if (!(mi instanceof ProxyMethodInvocation)) {
            throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
        }
        final ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
        JoinPoint jp = (JoinPoint) pmi.getUserAttribute(JOIN_POINT_KEY);
        if (jp == null) {
            jp = new MethodInvocationProceedingJoinPoint(pmi);
            pmi.setUserAttribute(JOIN_POINT_KEY, jp);
        }
        return jp;
    }


    private final Class<?> declaringClass;

    private final String methodName;

    private final Class<?>[] parameterTypes;

    protected transient Method aspectJAdviceMethod;

    private final AspectJExpressionPointcut pointcut;

    private final AspectInstanceFactory aspectInstanceFactory;

    /**
     *  切面 bean 的名称
     */
    private String aspectName = "";

    /**
     *  通知在切面内的声明顺序
     */
    private int declarationOrder;

    /**
     *  通知方法参数名称数组
     */
    @Nullable
    private String[] argumentNames;

    /** 异常通知:目标方法抛出的异常所绑定的参数名称 */
    @Nullable
    private String throwingName;

    /** 正常返回通知:目标方法的执行结果所绑定的参数名称  */
    @Nullable
    private String returningName;

    private Class<?> discoveredReturningType = Object.class;

    private Class<?> discoveredThrowingType = Object.class;

    /**
     * 通知方法的第一个参数为 JoinPoint,则为 0
     */
    private int joinPointArgumentIndex = -1;

    /**
     * 通知方法的第一个参数为 JoinPoint.StaticPart,则为 0
     */
    private int joinPointStaticPartArgumentIndex = -1;

    @Nullable
    private Map<String, Integer> argumentBindings;

    /**
     *  参数是否已经内省
     */
    private boolean argumentsIntrospected = false;

    @Nullable
    private Type discoveredReturningGenericType;
    // Note: Unlike return type, no such generic information is needed for the throwing type,
    // since Java doesn't allow exception types to be parameterized.

    public AbstractAspectJAdvice(
            Method aspectJAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aspectInstanceFactory) {

        Assert.notNull(aspectJAdviceMethod, "Advice method must not be null");
        declaringClass = aspectJAdviceMethod.getDeclaringClass();
        methodName = aspectJAdviceMethod.getName();
        parameterTypes = aspectJAdviceMethod.getParameterTypes();
        this.aspectJAdviceMethod = aspectJAdviceMethod;
        this.pointcut = pointcut;
        this.aspectInstanceFactory = aspectInstanceFactory;
    }


    public final Method getAspectJAdviceMethod() {
        return aspectJAdviceMethod;
    }

    public final AspectJExpressionPointcut getPointcut() {
        calculateArgumentBindings();
        return pointcut;
    }

    /**
     *  构建一个排除了 AspectJ 通知方法本身的安全切入点
     */
    public final Pointcut buildSafePointcut() {
        final Pointcut pc = getPointcut();
        final MethodMatcher safeMethodMatcher = MethodMatchers.intersection(
                new AdviceExcludingMethodMatcher(aspectJAdviceMethod), pc.getMethodMatcher());
        return new ComposablePointcut(pc.getClassFilter(), safeMethodMatcher);
    }

    public final AspectInstanceFactory getAspectInstanceFactory() {
        return aspectInstanceFactory;
    }

    @Nullable
    public final ClassLoader getAspectClassLoader() {
        return aspectInstanceFactory.getAspectClassLoader();
    }

    @Override
    public int getOrder() {
        return aspectInstanceFactory.getOrder();
    }

    public void setAspectName(String name) {
        aspectName = name;
    }

    @Override
    public String getAspectName() {
        return aspectName;
    }

    public void setDeclarationOrder(int order) {
        declarationOrder = order;
    }

    @Override
    public int getDeclarationOrder() {
        return declarationOrder;
    }

    public void setArgumentNames(String argNames) {
        final String[] tokens = StringUtils.commaDelimitedListToStringArray(argNames);
        setArgumentNamesFromStringArray(tokens);
    }

    public void setArgumentNamesFromStringArray(String... args) {
        argumentNames = new String[args.length];
        for (int i = 0; i < args.length; i++) {
            argumentNames[i] = StringUtils.trimWhitespace(args[i]);
            if (!isVariableName(argumentNames[i])) {
                throw new IllegalArgumentException(
                        "'argumentNames' property of AbstractAspectJAdvice contains an argument name '" +
                                argumentNames[i] + "' that is not a valid Java identifier");
            }
        }
        if (argumentNames != null) {
            if (aspectJAdviceMethod.getParameterCount() == argumentNames.length + 1) {
                // May need to add implicit join point arg name...
                final Class<?> firstArgType = aspectJAdviceMethod.getParameterTypes()[0];
                if (firstArgType == JoinPoint.class ||
                        firstArgType == ProceedingJoinPoint.class ||
                        firstArgType == JoinPoint.StaticPart.class) {
                    final String[] oldNames = argumentNames;
                    argumentNames = new String[oldNames.length + 1];
                    argumentNames[0] = "THIS_JOIN_POINT";
                    System.arraycopy(oldNames, 0, argumentNames, 1, oldNames.length);
                }
            }
        }
    }

    public void setReturningName(String name) {
        throw new UnsupportedOperationException("Only afterReturning advice can be used to bind a return value");
    }

    protected void setReturningNameNoCheck(String name) {
        // name could be a variable or a type...
        if (isVariableName(name)) {
            returningName = name;
        }
        else {
            // assume a type
            try {
                discoveredReturningType = ClassUtils.forName(name, getAspectClassLoader());
            }
            catch (final Throwable ex) {
                throw new IllegalArgumentException("Returning name '" + name  +
                        "' is neither a valid argument name nor the fully-qualified " +
                        "name of a Java type on the classpath. Root cause: " + ex);
            }
        }
    }

    protected Class<?> getDiscoveredReturningType() {
        return discoveredReturningType;
    }

    @Nullable
    protected Type getDiscoveredReturningGenericType() {
        return discoveredReturningGenericType;
    }

    public void setThrowingName(String name) {
        throw new UnsupportedOperationException("Only afterThrowing advice can be used to bind a thrown exception");
    }

    protected void setThrowingNameNoCheck(String name) {
        // name could be a variable or a type...
        if (isVariableName(name)) {
            throwingName = name;
        }
        else {
            // assume a type
            try {
                discoveredThrowingType = ClassUtils.forName(name, getAspectClassLoader());
            }
            catch (final Throwable ex) {
                throw new IllegalArgumentException("Throwing name '" + name  +
                        "' is neither a valid argument name nor the fully-qualified " +
                        "name of a Java type on the classpath. Root cause: " + ex);
            }
        }
    }

    protected Class<?> getDiscoveredThrowingType() {
        return discoveredThrowingType;
    }

    private boolean isVariableName(String name) {
        final char[] chars = name.toCharArray();
        if (!Character.isJavaIdentifierStart(chars[0])) {
            return false;
        }
        for (int i = 1; i < chars.length; i++) {
            if (!Character.isJavaIdentifierPart(chars[i])) {
                return false;
            }
        }
        return true;
    }


    /**
     *  1)如果第一个参数是 JoinPoint 或 ProceedingJoinPoint,则我们将传递一个 JoinPoint
     *  【如果是环绕通知,则传递 ProceedingJoinPoint】给它。
     *  2)如果第一个参数是 JoinPoint.StaticPart,则我们将传递一个 JoinPoint.StaticPart 给它。
     *  剩余的参数,切点将基于指定的连接点进行计算后执行绑定
     */
    public final synchronized void calculateArgumentBindings() {
        // 无需执行参数绑定操作
        if (argumentsIntrospected || parameterTypes.length == 0) {
            return;
        }

        // 未绑定的参数个数
        int numUnboundArgs = parameterTypes.length;
        // 通知方法的参数类型数组
        final Class<?>[] parameterTypes = aspectJAdviceMethod.getParameterTypes();
        /**
         *  第一个参数类型是 JoinPoint、ProceedingJoinPoint、JoinPoint.StaticPart,
         *  则将 numUnboundArgs 减 1
         */
        if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0]) ||
                maybeBindJoinPointStaticPart(parameterTypes[0])) {
            numUnboundArgs--;
        }

        if (numUnboundArgs > 0) {
            // 按照匹配的切入点,返回的名称绑定参数
            bindArgumentsByName(numUnboundArgs);
        }

        argumentsIntrospected = true;
    }

    /**
     *  是否是 JoinPoint
     */
    private boolean maybeBindJoinPoint(Class<?> candidateParameterType) {
        if (JoinPoint.class == candidateParameterType) {
            joinPointArgumentIndex = 0;
            return true;
        }
        else {
            return false;
        }
    }

    /**
     *  是否是 ProceedingJoinPoint
     */
    private boolean maybeBindProceedingJoinPoint(Class<?> candidateParameterType) {
        if (ProceedingJoinPoint.class == candidateParameterType) {
            if (!supportsProceedingJoinPoint()) {
                throw new IllegalArgumentException("ProceedingJoinPoint is only supported for around advice");
            }
            joinPointArgumentIndex = 0;
            return true;
        }
        else {
            return false;
        }
    }

    protected boolean supportsProceedingJoinPoint() {
        return false;
    }

    /**
     *  是否是 JoinPoint.StaticPart
     */
    private boolean maybeBindJoinPointStaticPart(Class<?> candidateParameterType) {
        if (JoinPoint.StaticPart.class == candidateParameterType) {
            joinPointStaticPartArgumentIndex = 0;
            return true;
        }
        else {
            return false;
        }
    }

    /**
     *  根据名称实现参数绑定
     */
    private void bindArgumentsByName(int numArgumentsExpectingToBind) {
        if (argumentNames == null) {
            // 读取参数名称数组
            argumentNames = createParameterNameDiscoverer().getParameterNames(aspectJAdviceMethod);
        }
        if (argumentNames != null) {
            // 绑定显示的参数
            bindExplicitArguments(numArgumentsExpectingToBind);
        }
        else {
            throw new IllegalStateException("Advice method [" + aspectJAdviceMethod.getName() + "] " +
                    "requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " +
                    "the argument names were not specified and could not be discovered.");
        }
    }

    /**
     *  创建一个用于实现参数绑定的 ParameterNameDiscoverer
     */
    protected ParameterNameDiscoverer createParameterNameDiscoverer() {
        final DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
        final AspectJAdviceParameterNameDiscoverer adviceParameterNameDiscoverer =
                new AspectJAdviceParameterNameDiscoverer(pointcut.getExpression());
        adviceParameterNameDiscoverer.setReturningName(returningName);
        adviceParameterNameDiscoverer.setThrowingName(throwingName);
        // Last in chain, so if we're called and we fail, that's bad...
        adviceParameterNameDiscoverer.setRaiseExceptions(true);
        discoverer.addDiscoverer(adviceParameterNameDiscoverer);
        return discoverer;
    }

    private void bindExplicitArguments(int numArgumentsLeftToBind) {
        Assert.state(argumentNames != null, "No argument names available");
        argumentBindings = new HashMap<>();

        final int numExpectedArgumentNames = aspectJAdviceMethod.getParameterCount();
        if (argumentNames.length != numExpectedArgumentNames) {
            throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
                    " arguments to bind by name in advice, but actually found " +
                    argumentNames.length + " arguments.");
        }

        // 需要显式绑定的参数起始索引
        final int argumentIndexOffset = parameterTypes.length - numArgumentsLeftToBind;
        for (int i = argumentIndexOffset; i < argumentNames.length; i++) {
            argumentBindings.put(argumentNames[i], i);
        }

        // 如果是 AfterReturning 通知 && 指定了绑定返回值的参数名称
        if (returningName != null) {
            // 通知方法中不存在此绑定参数,则抛出 IllegalStateException 异常
            if (!argumentBindings.containsKey(returningName)) {
                throw new IllegalStateException("Returning argument name '" + returningName +
                        "' was not bound in advice arguments");
            }
            else {
                // 读取参数索引
                final Integer index = argumentBindings.get(returningName);
                // 写入返回值类型
                discoveredReturningType = aspectJAdviceMethod.getParameterTypes()[index];
                // 写入返回值泛型
                discoveredReturningGenericType = aspectJAdviceMethod.getGenericParameterTypes()[index];
            }
        }
        // 如果是 AfterThrowing 通知 && 指定了绑定异常的参数名称
        if (throwingName != null) {
            // 通知方法中不存在此绑定参数,则抛出 IllegalStateException 异常
            if (!argumentBindings.containsKey(throwingName)) {
                throw new IllegalStateException("Throwing argument name '" + throwingName +
                        "' was not bound in advice arguments");
            }
            else {
                // 读取参数索引
                final Integer index = argumentBindings.get(throwingName);
                // 写入异常类型
                discoveredThrowingType = aspectJAdviceMethod.getParameterTypes()[index];
            }
        }

        // 按需配置切点表达式
        configurePointcutParameters(argumentNames, argumentIndexOffset);
    }

    private void configurePointcutParameters(String[] argumentNames, int argumentIndexOffset) {
        int numParametersToRemove = argumentIndexOffset;
        if (returningName != null) {
            numParametersToRemove++;
        }
        if (throwingName != null) {
            numParametersToRemove++;
        }
        // 需要执行绑定的切点参数名称数组
        final String[] pointcutParameterNames = new String[argumentNames.length - numParametersToRemove];
        // 需要执行绑定的切点参数类型数组
        final Class<?>[] pointcutParameterTypes = new Class<?>[pointcutParameterNames.length];
        // 通知方法参数类型数组
        final Class<?>[] methodParameterTypes = aspectJAdviceMethod.getParameterTypes();

        int index = 0;
        for (int i = 0; i < argumentNames.length; i++) {
            // 尝试跳过第一个参数
            if (i < argumentIndexOffset) {
                continue;
            }
            // 尝试跳过 returningName 和 throwingName 参数
            if (argumentNames[i].equals(returningName) ||
                    argumentNames[i].equals(throwingName)) {
                continue;
            }
            pointcutParameterNames[index] = argumentNames[i];
            pointcutParameterTypes[index] = methodParameterTypes[i];
            index++;
        }
        // 写入切点参数名称数组
        pointcut.setParameterNames(pointcutParameterNames);
        // 写入切点参数名称类型数组
        pointcut.setParameterTypes(pointcutParameterTypes);
    }

    /**
     * 执行参数绑定并返回绑定后的参数列表
     */
    protected Object[] argBinding(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
            @Nullable Object returnValue, @Nullable Throwable ex) {
        calculateArgumentBindings();

        // AMC start
        final Object[] adviceInvocationArgs = new Object[parameterTypes.length];
        int numBound = 0;

        if (joinPointArgumentIndex != -1) {
            adviceInvocationArgs[joinPointArgumentIndex] = jp;
            numBound++;
        }
        else if (joinPointStaticPartArgumentIndex != -1) {
            adviceInvocationArgs[joinPointStaticPartArgumentIndex] = jp.getStaticPart();
            numBound++;
        }

        if (!CollectionUtils.isEmpty(argumentBindings)) {
            // binding from pointcut match
            if (jpMatch != null) {
                final PointcutParameter[] parameterBindings = jpMatch.getParameterBindings();
                for (final PointcutParameter parameter : parameterBindings) {
                    final String name = parameter.getName();
                    final Integer index = argumentBindings.get(name);
                    adviceInvocationArgs[index] = parameter.getBinding();
                    numBound++;
                }
            }
            // binding from returning clause
            if (returningName != null) {
                final Integer index = argumentBindings.get(returningName);
                adviceInvocationArgs[index] = returnValue;
                numBound++;
            }
            // binding from thrown exception
            if (throwingName != null) {
                final Integer index = argumentBindings.get(throwingName);
                adviceInvocationArgs[index] = ex;
                numBound++;
            }
        }

        if (numBound != parameterTypes.length) {
            throw new IllegalStateException("Required to bind " + parameterTypes.length +
                    " arguments, but only bound " + numBound + " (JoinPointMatch " +
                    (jpMatch == null ? "was NOT" : "WAS") + " bound in invocation)");
        }

        return adviceInvocationArgs;
    }


    /**
     *  执行通知方法
     */
    protected Object invokeAdviceMethod(
            @Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex)
                    throws Throwable {
        return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
    }

    protected Object invokeAdviceMethod(JoinPoint jp, @Nullable JoinPointMatch jpMatch,
            @Nullable Object returnValue, @Nullable Throwable t) throws Throwable {
        return invokeAdviceMethodWithGivenArgs(argBinding(jp, jpMatch, returnValue, t));
    }

    protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
        Object[] actualArgs = args;
        if (aspectJAdviceMethod.getParameterCount() == 0) {
            actualArgs = null;
        }
        try {
            ReflectionUtils.makeAccessible(aspectJAdviceMethod);
            // TODO AopUtils.invokeJoinpointUsingReflection
            return aspectJAdviceMethod.invoke(aspectInstanceFactory.getAspectInstance(), actualArgs);
        }
        catch (final IllegalArgumentException ex) {
            throw new AopInvocationException("Mismatch on arguments to advice method [" +
                    aspectJAdviceMethod + "]; pointcut expression [" +
                    pointcut.getPointcutExpression() + "]", ex);
        }
        catch (final InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }

    protected JoinPoint getJoinPoint() {
        return currentJoinPoint();
    }

    @Nullable
    protected JoinPointMatch getJoinPointMatch() {
        final MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
        if (!(mi instanceof ProxyMethodInvocation)) {
            throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
        }
        return getJoinPointMatch((ProxyMethodInvocation) mi);
    }

    @Nullable
    protected JoinPointMatch getJoinPointMatch(ProxyMethodInvocation pmi) {
        final String expression = pointcut.getExpression();
        return expression != null ? (JoinPointMatch) pmi.getUserAttribute(expression) : null;
    }


    @Override
    public String toString() {
        return getClass().getName() + ": advice method [" + aspectJAdviceMethod + "]; " +
                "aspect name '" + aspectName + "'";
    }

    /**
     *  排除指定通知方法的 MethodMatcher
     * MethodMatcher that excludes the specified advice method.
     * @see AbstractAspectJAdvice#buildSafePointcut()
     */
    private static class AdviceExcludingMethodMatcher extends StaticMethodMatcher {
        private final Method adviceMethod;

        public AdviceExcludingMethodMatcher(Method adviceMethod) {
            this.adviceMethod = adviceMethod;
        }

        @Override
        public boolean matches(Method method, Class<?> targetClass) {
            return !adviceMethod.equals(method);
        }

        @Override
        public boolean equals(Object other) {
            if (this == other) {
                return true;
            }
            if (!(other instanceof AdviceExcludingMethodMatcher)) {
                return false;
            }
            final AdviceExcludingMethodMatcher otherMm = (AdviceExcludingMethodMatcher) other;
            return adviceMethod.equals(otherMm.adviceMethod);
        }

        @Override
        public int hashCode() {
            return adviceMethod.hashCode();
        }
    }
}

@SuppressWarnings("serial")
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable {

    public AspectJMethodBeforeAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }

    @Override
    public void before(Method method, Object[] args, @Nullable Object target) throws Throwable {
        invokeAdviceMethod(getJoinPointMatch(), null, null);
    }

    @Override
    public boolean isBeforeAdvice() {
        return true;
    }

    @Override
    public boolean isAfterAdvice() {
        return false;
    }
}

@SuppressWarnings("serial")
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {

    public AspectJAroundAdvice(
            Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJAroundAdviceMethod, pointcut, aif);
    }

    @Override
    public boolean isBeforeAdvice() {
        return false;
    }

    @Override
    public boolean isAfterAdvice() {
        return false;
    }

    @Override
    protected boolean supportsProceedingJoinPoint() {
        return true;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        if (!(mi instanceof ProxyMethodInvocation)) {
            throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
        }
        final ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
        final ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
        final JoinPointMatch jpm = getJoinPointMatch(pmi);
        return invokeAdviceMethod(pjp, jpm, null, null);
    }

    /**
     * Return the ProceedingJoinPoint for the current invocation,
     */
    protected ProceedingJoinPoint lazyGetProceedingJoinPoint(ProxyMethodInvocation rmi) {
        return new MethodInvocationProceedingJoinPoint(rmi);
    }

}

@SuppressWarnings("serial")
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice
implements AfterReturningAdvice, AfterAdvice, Serializable {

    public AspectJAfterReturningAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }


    @Override
    public boolean isBeforeAdvice() {
        return false;
    }

    @Override
    public boolean isAfterAdvice() {
        return true;
    }

    @Override
    public void setReturningName(String name) {
        setReturningNameNoCheck(name);
    }

    @Override
    public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable {
        // 如果返回值类型和关联的通知参数类型匹配,则执行返回通知
        if (shouldInvokeOnReturnValueOf(method, returnValue)) {
            invokeAdviceMethod(getJoinPointMatch(), returnValue, null);
        }
    }

    private boolean shouldInvokeOnReturnValueOf(Method method, @Nullable Object returnValue) {
        final Class<?> type = getDiscoveredReturningType();
        final Type genericType = getDiscoveredReturningGenericType();
        // If we aren't dealing with a raw type, check if generic parameters are assignable.
        return matchesReturnValue(type, method, returnValue) &&
                (genericType == null || genericType == type ||
                TypeUtils.isAssignable(genericType, method.getGenericReturnType()));
    }

    /**
     *  返回值类型是否匹配
     */
    private boolean matchesReturnValue(Class<?> type, Method method, @Nullable Object returnValue) {
        if (returnValue != null) {
            return ClassUtils.isAssignableValue(type, returnValue);
        }
        else if (Object.class == type && void.class == method.getReturnType()) {
            return true;
        }
        else {
            return ClassUtils.isAssignable(type, method.getReturnType());
        }
    }

}


@SuppressWarnings("serial")
public class AspectJAfterAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {

    public AspectJAfterAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            // 执行目标方法
            return mi.proceed();
        }
        finally {
            invokeAdviceMethod(getJoinPointMatch(), null, null);
        }
    }

    @Override
    public boolean isBeforeAdvice() {
        return false;
    }

    @Override
    public boolean isAfterAdvice() {
        return true;
    }
}

@SuppressWarnings("serial")
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
implements MethodInterceptor, AfterAdvice, Serializable {

    public AspectJAfterThrowingAdvice(
            Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }

    @Override
    public boolean isBeforeAdvice() {
        return false;
    }

    @Override
    public boolean isAfterAdvice() {
        return true;
    }

    @Override
    public void setThrowingName(String name) {
        setThrowingNameNoCheck(name);
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        try {
            return mi.proceed();
        }
        catch (final Throwable ex) {
            // 是否需要执行异常通知
            if (shouldInvokeOnThrowing(ex)) {
                invokeAdviceMethod(getJoinPointMatch(), null, ex);
            }
            throw ex;
        }
    }

    /**
     *  异常类型是否和通知方法中的参数匹配
     */
    private boolean shouldInvokeOnThrowing(Throwable ex) {
        return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
    }
}

猜你喜欢

转载自www.cnblogs.com/zhuxudong/p/10327804.html