美文网首页
Spring aop(3)2018-08-14

Spring aop(3)2018-08-14

作者: Seetheworl_6675 | 来源:发表于2018-08-14 00:19 被阅读0次

接着上一节Spring aop(2):
2.3: this.addAdvisorsFromAspectInstanceFactory获取advisor:
a、我们先来看下advisor的接口定义:

public interface Advisor {
    Advice EMPTY_ADVICE = new Advice() {
    };

    Advice getAdvice();

    boolean isPerInstance();
}

从接口定义可以看出:advisor就是组合了Advice

b、addAdvisorsFromAspectInstanceFactory的代码:

private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();

private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
        //获取Advisors集合
        List<Advisor> advisors = this.aspectFactory.getAdvisors(instanceFactory);
        //从中挑出适用于目标对象的Advisor
        advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
        AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
        //对获取到的Advisor进行排序
        AnnotationAwareOrderComparator.sort(advisors);
        //将获取到Advisor添加到advisors集合中
        addAdvisors(advisors);
    }

从代码中我们可以看出:addAdvisorsFromAspectInstanceFactory先从ReflectiveAspectJAdvisorFactory中的getAdvisor从MetadataAwareAspectInstanceFactory中获取advisors。然后根据目标类进行过滤、排序,最后添加到advisors集合中。

c、我们接着看getAdvisors方法:

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
         //切面类
        Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        //切面类名字
        String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
        //校验切面类
        validate(aspectClass);

        // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator(装饰模式的一个使用)
        // so that it will only instantiate once. (确保只能获取到一个切面实例)
        // //将我们上一步获取的MetadataAwareAspectInstanceFactory实例又包装为LazySingletonAspectInstanceFactoryDecorator
        MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
                new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

        List<Advisor> advisors = new LinkedList<>();
         //调用getAdvisorMethods方法来获取切面类中所有不包含Pointcut注解的方法。
        for (Method method : getAdvisorMethods(aspectClass)) {
             //得到Advisor
            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()) {
            Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
            advisors.add(0, instantiationAdvisor);
        }

        // Find introduction fields.
         //查找引入增强,并加到集合中。
        for (Field field : aspectClass.getDeclaredFields()) {
            Advisor advisor = getDeclareParentsAdvisor(field);
            if (advisor != null) {
                advisors.add(advisor);
            }
        }

        return advisors;
    }

d、这边我们看下是validate(aspectClass)是什么校验的:

//校验我们的切面类是否带有Aspect注解
 public void validate(Class<?> aspectClass) throws AopConfigException {
        //如果我们的带有@Aspect注解的类的父类也带有@Aspect注解并且其还不是抽象类 则抛出异常
        if (aspectClass.getSuperclass().getAnnotation(Aspect.class) != null &&
                !Modifier.isAbstract(aspectClass.getSuperclass().getModifiers())) {
            throw new AopConfigException("[" + aspectClass.getName() + "] cannot extend concrete aspect [" +
                    aspectClass.getSuperclass().getName() + "]");
        }
        AjType<?> ajType = AjTypeSystem.getAjType(aspectClass);
        //再次校验 切面类是否带有 @Aspect注解
        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.");
        }
    }

e、接着我们getAdvisorMethods(aspectClass)方法:

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
        final List<Method> methods = new LinkedList<Method>();
 
        ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
            //ReflectionUtils.MethodCallback的匿名实现
            @Override
            public void doWith(Method method) throws IllegalArgumentException {
                // Exclude pointcuts
                //不带Pointcut注解的方法 添加到methods集合中
                if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                    methods.add(method);
                }
            }
        });
        Collections.sort(methods, METHOD_COMPARATOR);
        return methods;
    }

f、接着我们看下getAdvisor方法:

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
            int declarationOrderInAspect, String aspectName) {
        //验证切面类
        validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        //这里根据传入的方法和切面类获取 切点表达式
        AspectJExpressionPointcut expressionPointcut = getPointcut(
                candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
        //没有获取到切点表达式 直接返回null
        if (expressionPointcut == null) {
            return null;
        }
        //返回一个Advisor的实例 这个实例中包含了 一下内容
        //(1、切点表达式 AspectJExpressionPointcut 
        //2、切点方法 
        //3、ReflectiveAspectJAdvisorFactory工厂实例
        //4、切面类实例
        //5、切面类名字
        return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
                this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    }

j、getAdvisor 中的getPointcut获取切点表达式方法:

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
        //查找方法上存在切面注解(通知类型注解) 即方法上是否有
        //@Before, @Around, @After, @AfterReturning, @AfterThrowing, @Pointcut注解并返回AspectJAnnotation的类型
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }
        //创建AspectJExpressionPointcut对象
        AspectJExpressionPointcut ajexp =
                new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
        //设置切面表达式
        ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
        ajexp.setBeanFactory(this.beanFactory);
        return ajexp;
    }

     @Nullable
    protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
        Class<?>[] classesToLookFor = new Class<?>[] {
                Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
        for (Class<?> c : classesToLookFor) {
            AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
            if (foundAnnotation != null) {
                return foundAnnotation;
            }
        }
        return null;
    }

g、接着我们看下getAdvisor方法中的InstantiationModelAwarePointcutAdvisorImpl对象的构造方法:

 public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
            Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
        //切点表达式类 AspectJExpressionPointcut 
        this.declaredPointcut = declaredPointcut;
        //切面类 
        this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
        //切点表达式方法所在的方法名 这里指的是@Before、@After这些通知类型所在的方法名
        this.methodName = aspectJAdviceMethod.getName();
        //通知参数类型
        this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
        //切面通知方法
        this.aspectJAdviceMethod = aspectJAdviceMethod;
        //ReflectiveAspectJAdvisorFactory实例
        this.aspectJAdvisorFactory = aspectJAdvisorFactory;
        //切面对象实例
        this.aspectInstanceFactory = aspectInstanceFactory;
        //切面顺序
        this.declarationOrder = declarationOrder;
        this.aspectName = aspectName;
        //根据切面元数据判断是否要延迟实例化 一般为否
        if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
            // Static part of the pointcut is a lazy type.
            Pointcut preInstantiationPointcut = Pointcuts.union(
                    aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
            this.pointcut = new PerTargetInstantiationModelPointcut(
                    this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
            this.lazy = true;
        }
        else {
            // A singleton aspect.
            //切点表达式类
            this.pointcut = this.declaredPointcut;
            this.lazy = false;
            //这里获取Advice实例 
            this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
        }
    }

l、接着我们看下InstantiationModelAwarePointcutAdvisorImpl构造方法中的
instantiateAdvice(this.declaredPointcut)方法:

private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
    //入参为:通知方法、切点表达式类、切面实例、切面的一个顺序、切面类名
    return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
            this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
    }


public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
            MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
        //切面类 带有@Aspect注解的类
        Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
        //验证切面类
        validate(candidateAspectClass);
        //根据通知方法 获取通知注解相关信息
        AspectJAnnotation<?> aspectJAnnotation =
                AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
        if (aspectJAnnotation == null) {
            return null;
        }
        //校验不是切面类则抛出异常
        if (!isAspect(candidateAspectClass)) {
            throw new AopConfigException("Advice must be declared inside an aspect type: " +
                    "Offending method '" + candidateAdviceMethod + "' in class [" +
                    candidateAspectClass.getName() + "]");
        }
        AbstractAspectJAdvice springAdvice;
        //获取通知类型
        switch (aspectJAnnotation.getAnnotationType()) {
            //如果是前置通知,则直接创建AspectJMethodBeforeAdvice实例
            //入参为:通知方法、切点表达式、切面实例
            case AtBefore:
                springAdvice = new AspectJMethodBeforeAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            //如果是后置通知,则直接创建AspectJAfterAdvice实例
            //入参为:通知方法、切点表达式、切面实例
            case AtAfter:
                springAdvice = new AspectJAfterAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            //如果是后置返回通知,则直接创建AspectJAfterReturningAdvice实例
            //入参为:通知方法、切点表达式、切面实例
            case AtAfterReturning:
                springAdvice = new AspectJAfterReturningAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
                //设置后置返回值的参数name
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                    springAdvice.setReturningName(afterReturningAnnotation.returning());
                }
                break;
            //如果是后置异常通知,则直接创建AspectJAfterThrowingAdvice实例
            //入参为:通知方法、切点表达式、切面实例
            case AtAfterThrowing:
                springAdvice = new AspectJAfterThrowingAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
                //设置后置异常通知 异常类型参数name
                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                    springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
                }
                break;
            //如果是后置异常通知,则直接创建AspectJAfterThrowingAdvice实例
            //入参为:通知方法、切点表达式、切面实例
            case AtAround:
                springAdvice = new AspectJAroundAdvice(
                        candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                break;
            //如果是切点方法,则什么也不做
            case AtPointcut:
                if (logger.isDebugEnabled()) {
                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }
                return null;
            //上面的那几种情况都不是的话,则抛出异常
            default:
                throw new UnsupportedOperationException(
                        "Unsupported advice type on method: " + candidateAdviceMethod);
        }

        // Now to configure the advice...
        //切面的名字
        springAdvice.setAspectName(aspectName);
        springAdvice.setDeclarationOrder(declarationOrder);
        //通知注解中的参数名
        String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
        if (argNames != null) {
            springAdvice.setArgumentNamesFromStringArray(argNames);
        }
        //参数绑定
        springAdvice.calculateArgumentBindings();
        return springAdvice;
    }

今天先到这里。。。。

相关文章

网友评论

      本文标题:Spring aop(3)2018-08-14

      本文链接:https://www.haomeiwen.com/subject/obvpbftx.html