@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());
    }
}

原文地址:https://www.cnblogs.com/zhuxudong/p/10327804.html

时间: 2024-10-14 07:18:10

@Aspect 注解切面解析的相关文章

SpringCloud快捷创建注解切面

首先需要明白,实现AOP的切面主要有以下几个要素: 使用@Aspect注解将一个java类定义为切面类 使用@Pointcut定义一个切入点,可以是一个规则表达式,比如下例中某个package下的所有函数,也可以是一个注解等. 根据需要在切入点不同位置的切入内容 使用@Before在切入点开始处切入内容 使用@After在切入点结尾处切入内容 使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理) 使用@Around在切入点前后切入内容,并自

Java注解全面解析(转)

1.基本语法 注解定义看起来很像接口的定义.事实上,与其他任何接口一样,注解也将会编译成class文件. @Target(ElementType.Method) @Retention(RetentionPolicy.RUNTIME) public @interface Test {} 除了@符号以外,@Test的定义很像一个空的接口.定义注解时,需要一些元注解(meta-annotation),如@Target和@Retention @Target用来定义注解将应用于什么地方(如一个方法或者一个

[笔记]Java注解全面解析

JAVA注解 注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举是在同一个层次.它可以声明在包.类.字段.方法.局部变量.方法参数等的前面,用来对这些元素进行说明,注释. 1.注解分类 1.1按照运行机制分类 源码注解 注解只在源码中存在,编译成.class文件就不存在了 编译时注解 注解在源码和.class文件中都存在 比如: @Override @Deprecated @Suppvisewarnings 运行时注解 在运行

Spring @Aspect实现切面编程

参考:http://blog.csdn.net/cdl2008sky/article/details/6268628 Spring @Aspect实现切面编程: XML: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springf

【面试加分项】java自定义注解之解析注解

我之前的博客中说明过自定义注解的声明今天我们来看看如何对我们自己定义的注解进行使用. 1.我们在程序中使用我们的注解. 上一篇中我们自定义了一个注解: @Target(ElementType.FIELD)//注解的作用范围,就是注解是用在什么地方的 @Retention(RetentionPolicy.RUNTIME)//注解的级别,就是注解能留存到什么时候 @Documented @Inherited public @interface MyAnnotation { public String

【面试加分项】java自己定义注解之解析注解

我之前的博客中说明过自己定义注解的声明今天我们来看看怎样对我们自己定义的注解进行使用. 1.我们在程序中使用我们的注解. 上一篇中我们自己定义了一个注解: @Target(ElementType.FIELD)//注解的作用范围.就是注解是用在什么地方的 @Retention(RetentionPolicy.RUNTIME)//注解的级别,就是注解能留存到什么时候 @Documented @Inherited public @interface MyAnnotation { public Stri

RequestMapping 注解的解析、匹配、注册

RequestMapping 注解的解析.匹配.注册 1)创建 RequestMappingHandlerMapping 实例时会触发 afterPropertiesSet 调用. 2)读取容器中所有带有 Controller 或 RequestMapping 注解的类. 3)读取此类中所有满足过滤器 ReflectionUtils.USER_DECLARED_METHODS 的方法, 读取处理方法上的 RequestMapping 注解信息, 将其解析并封装为 RequestMappingIn

[Spring实战系列](18)注解切面

使用注解来创建切面是AspectJ 5所引入的关键特性.在AspectJ 5之前,编写AspectJ切面需要学习一种Java语言的扩展,但是AspectJ面向注解的模型可以非常简单的通过少量注解把任意类转变为切面. 回顾一下Audience类,没有任何地方让它成为一个切面,我们不得不使用XML声明通知和切点. 我们通过@AspectJ注解,我们再看看Audience类,不需要任何额外的类或Bean声明就能将它转换为一个切面. package com.sjf.bean; /** * 歌手实体类 *

【Spring实战】—— 13 AspectJ注解切面

前面了解了典型的AOP基于配置的使用方法,下面介绍下如何依赖于注解来实现AOP. 基于注解降低了配置文件的复杂程度,但是引入了程序间的耦合,其中的优劣待用户自己判断了. 需要注意的是,确定AspectJ与JDK之间的版本,否则会报错,详情请见. 首先看一下基于注解的切面类,这时的切面不仅仅是一个POJO类了,与AOP进行了紧密的耦合.但是配置过程和方式都与原来的方式差不多. package com.spring.test.chap44; import org.aspectj.lang.annot