zoukankan      html  css  js  c++  java
  • @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());
        }
    }
    
  • 相关阅读:
    synchronized一个(二)
    org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
    java.lang.AbstractMethodError: org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout
    NTFS簇大小对硬盘性能的影响测试
    Win10 开机自动打开上次未关闭程序怎么办
    Win10快速访问怎么关闭?
    激活windows 10 LTSC 2019(无需工具)
    WPS文字双行合一
    插入百度地图代码后,页面文字不能被选中的解决方案
    WPS文字批量选中整行(以第?章为例)
  • 原文地址:https://www.cnblogs.com/zhuxudong/p/10327804.html
Copyright © 2011-2022 走看看