乐趣区

关于java:SpringBoot-aop-源码学习笔记

spring aop 中次要的主件次要分为以下几个局部:

  1. advisorCreator 继承 spring ioc 的扩大接口 beanPostProcessor,次要用来扫描获取 advisor;
  2. advisor spring aop 参谋的意思,封装了 spring aop 中的切点和告诉;
  3. advice spring aop 的切点,即 aop 的加强办法;

    springBoot aop 的入口在 AopAutoConfiguration 这个类中,因为 springBoot 的主动拆卸中,是开启 aop 的,即 spring.aop.auto=true,同样默认配置 proxy-target-class 的至为 true,因而默认应用 cglib 来做动静代理。

@Configuration(proxyBeanMethods = false)  
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)  
public class AopAutoConfiguration {@Configuration(proxyBeanMethods = false)  
   @ConditionalOnClass(Advice.class)  
   static class AspectJAutoProxyingConfiguration {@Configuration(proxyBeanMethods = false)  
      @EnableAspectJAutoProxy(proxyTargetClass = false)  
      @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",  
            matchIfMissing = false)  
      static class JdkDynamicAutoProxyConfiguration { }  
  
      @Configuration(proxyBeanMethods = false)  
      @EnableAspectJAutoProxy(proxyTargetClass = true)  
      @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",  
            matchIfMissing = true)  
      static class CglibAutoProxyConfiguration {}}    
  
}

跟进 @EnableAspectJAutoProxy 这个标签:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

    /**
     * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
     * to standard Java interface-based proxies. The default is {@code false}.
     */
    boolean proxyTargetClass() default false;

    /**
     * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
     * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
     * Off by default, i.e. no guarantees that {@code AopContext} access will work.
     * @since 4.3.1
     */
    boolean exposeProxy() default false;}

咱们能够看到往 ioc 容器中注入了一个 AspectJAutoProxyRegistrar 的类,跟进之, 咱们能够看到调用了 AopConfigUtil 的 registerAspectJAnnotationAutoProxyCreatorIfNecessary 办法,持续跟进咱们能够看到:往容器外面注入了一个 AnnotationAwareAspectJAutoProxyCreator 的 bean。

@Nullable  
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);  
}

此外,AnnotationAwareAspectJAutoProxyCreator 的父类实现了 BeanFactoryAware 接口,在该办法中会调用其的 initBeanFactory 办法,如下:次要是实例化了 AnnotationAwareAspectJAutoProxyCreator 中的 aspectJAdvisorsBuilder 属性,该属性提供了后续的 advisor 的创立工作。

@Override  
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {super.initBeanFactory(beanFactory);  
   if (this.aspectJAdvisorFactory == null) {this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);  
   }  
   this.aspectJAdvisorsBuilder =  
         new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);  
}

因为 AnnotationAwareAspectJAutoProxyCreator 实现了 Spring 的后置处理器,而 PointcutAdvisor 创立是在其的 postProcessBeforeInstantiation 的办法中:

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {Object cacheKey = getCacheKey(beanClass, beanName);

        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {if (this.advisedBeans.containsKey(cacheKey)) {return null;}
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }

        // Create proxy here if we have a custom TargetSource.
        // Suppresses unnecessary default instantiation of the target bean:
        // The TargetSource will handle target instances in a custom fashion.
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {if (StringUtils.hasLength(beanName)) {this.targetSourcedBeans.add(beanName);
            }
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy;
        }

        return null;
    }

这里的 isInfrastructureClass 办法次要是判断以后 bean 是否是 PointCut, Advice 等 aop 相干的类,如果是的话则该 bean 不能被代理。再来看下 shouldSkip 办法,改办法中蕴含了 adivor 的创立:

protected boolean shouldSkip(Class<?> beanClass, String beanName) {  
   // TODO: Consider optimization by caching the list of the aspect names  
 List<Advisor> candidateAdvisors = findCandidateAdvisors();  
   for (Advisor advisor : candidateAdvisors) {  
      if (advisor instanceof AspectJPointcutAdvisor &&  
            ((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {return true;}  
   }  
   return super.shouldSkip(beanClass, beanName);  
}

跟进 findCandidateAdvisors 办法,这里次要看 aspectJAdvisorsBuilder 的 buildAspectJAdvisors 办法

@Override  
protected List<Advisor> findCandidateAdvisors() {  
   // Add all the Spring advisors found according to superclass rules.  
 List<Advisor> advisors = super.findCandidateAdvisors();  
   // Build Advisors for all AspectJ aspects in the bean factory.  
 if (this.aspectJAdvisorsBuilder != null) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());  
   }  
   return advisors;  
}

该办法中有个判断条件 this.advisorFactory.isAspect(beanType) 判断该 bean 是否打了 @Aspect 标签,再去做生成 advisor 的操作。这里会调用 advisorFactory 的 getAdvisors 办法。获取到 advisors 后并把之放入 advisorsCache 的缓存中。跟进 getAdvisors 办法:

public List<Advisor> buildAspectJAdvisors() {  
   List<String> aspectNames = this.aspectBeanNames;  
   
   if (aspectNames == null) {synchronized (this) {  
         aspectNames = this.aspectBeanNames;  
         if (aspectNames == null) {List<Advisor> advisors = new ArrayList<>();  
            aspectNames = new ArrayList<>();  
            String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);  
            for (String beanName : beanNames) {if (!isEligibleBean(beanName)) {continue;}  
               // We must be careful not to instantiate beans eagerly as in this case they  
 // would be cached by the Spring container but would not have been weaved. Class<?> beanType = this.beanFactory.getType(beanName);  
               if (beanType == null) {continue;}  
               if (this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);  
                  AspectMetadata amd = new AspectMetadata(beanType, beanName);  
                  if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {  
                     MetadataAwareAspectInstanceFactory factory =  
                           new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);  
                     List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);  
                     if (this.beanFactory.isSingleton(beanName)) {this.advisorsCache.put(beanName, classAdvisors);  
                     }  
                     else {this.aspectFactoryCache.put(beanName, factory);  
                     }  
                     advisors.addAll(classAdvisors);  
                  }  
                  else {  
                     // Per target or per this.  
 if (this.beanFactory.isSingleton(beanName)) {  
                        throw new IllegalArgumentException("Bean with name'" + beanName +  
                              "'is a singleton, but aspect instantiation model is not singleton");  
                     }  
                     MetadataAwareAspectInstanceFactory factory =  
                           new PrototypeAspectInstanceFactory(this.beanFactory, beanName);  
                     this.aspectFactoryCache.put(beanName, factory);  
                     advisors.addAll(this.advisorFactory.getAdvisors(factory));  
                  }  
               }  
            }  
            this.aspectBeanNames = aspectNames;  
            return advisors;  
         }  
      }  
   }  
 
   if (aspectNames.isEmpty()) {return Collections.emptyList();  
   }  
   List<Advisor> advisors = new ArrayList<>();  
   for (String aspectName : aspectNames) {List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);  
      if (cachedAdvisors != null) {advisors.addAll(cachedAdvisors);  
      }  
      else {MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);  
         advisors.addAll(this.advisorFactory.getAdvisors(factory));  
      }  
   }  
   return advisors;  
}

这里的 getAdvisorMethods 办法获取了该类中除打了 @PointCut 的办法,而后依据 getAdvisor 办法获取 advisor,跟进之

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 lazySingletonAspectInstanceFactory =  
         new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);  
  
   List<Advisor> advisors = new ArrayList<>();  
   for (Method method : getAdvisorMethods(aspectClass)) {// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect  
 // to getAdvisor(...) to represent the "current position" in the declared methods list. // However, since Java 7 the "current position" is not valid since the JDK no longer // returns declared methods in the order in which they are declared in the source code. // Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods // discovered via reflection in order to support reliable advice ordering across JVM launches. // Specifically, a value of 0 aligns with the default value used in // AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor). Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, 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;  
}

咱们能够看到返回了一个 InstantiationModelAwarePointcutAdvisorImpl 的 bean,而在该 bean 的结构器中会调用 aspectJAdvisorFactory 的 getAdvice 的办法从而获取 Advice:

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,  
      int declarationOrderInAspect, String aspectName) {validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());  
  
   AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());  
   if (expressionPointcut == null) {return null;}  
  
   return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,  
         this, aspectInstanceFactory, declarationOrderInAspect, aspectName);  
}

依据办法上的标签类型来确定告诉的类型。

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

        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 afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {springAdvice.setReturningName(afterReturningAnnotation.returning());
                }
                break;
            case AtAfterThrowing:
                springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
                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);
        }

        // 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;
    }

生成参谋和告诉之后,下一步就是创立代理类了, springBoot 默认采纳 cglib 来创立动静代理,代理类的创立在 spring 后置处理器的 postProcessAfterInitialization 中实现:

    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

跟进 wrapIfNecessary 办法,重点看 getAdvicesAndAdvisorsForBean 办法,该办法是获取 bean 的告诉和加强办法,如果一个都没找到,间接返回 bean, 只有找到,就创立代理对象。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}  
   if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}  
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);  
      return bean;  
   }  
  
   // Create proxy if we have advice.  
 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);  
   if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);  
      Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));  
      this.proxyTypes.put(cacheKey, proxy.getClass());  
      return proxy;  
   }  
  
   this.advisedBeans.put(cacheKey, Boolean.FALSE);  
   return bean;  
}

跟进 getAdvicesAndAdvisorsForBean 办法,其中要害办法为 findEligibleAdvisors,这里的 findCandidateAdvisors 能够从缓存中失去之前创立的 advisor。而 findAdvisorsThatCanApply 办法则是为 bean 寻找相匹配的告诉和加强办法,跟进之。

    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {List<Advisor> candidateAdvisors = findCandidateAdvisors();
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

持续跟进会进入 AopUtil 的 findAdvisorsThatCanApply 办法:

    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");
        if (!pc.getClassFilter().matches(targetClass)) {return false;}

        MethodMatcher methodMatcher = pc.getMethodMatcher();
        if (methodMatcher == MethodMatcher.TRUE) {
            // No need to iterate the methods if we're matching any method anyway...
            return true;
        }

        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        Set<Class<?>> classes = new LinkedHashSet<>();
        if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));
        }
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        for (Class<?> clazz : classes) {Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            for (Method method : methods) {
                if (introductionAwareMethodMatcher != null ?
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                        methodMatcher.matches(method, targetClass)) {return true;}
            }
        }

        return false;
    }

该办法中会调用 canApply 办法去判断 advisor 和以后的 bean 是否匹配:

    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
        }
        else if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca = (PointcutAdvisor) advisor;
            return canApply(pca.getPointcut(), targetClass, hasIntroductions);
        }
        else {
            // It doesn't have a pointcut so we assume it applies.
            return true;
        }
    }

因为咱们之前创立的 advvisor 为 InstantiationModelAwarePointcutAdvisorImpl,该类实现了 PointcutAdvisor 接口,这里走 canApply 办法:


    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");
        if (!pc.getClassFilter().matches(targetClass)) {return false;}

        MethodMatcher methodMatcher = pc.getMethodMatcher();
        if (methodMatcher == MethodMatcher.TRUE) {
            // No need to iterate the methods if we're matching any method anyway...
            return true;
        }

        IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
        if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
        }

        Set<Class<?>> classes = new LinkedHashSet<>();
        if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));
        }
        classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

        for (Class<?> clazz : classes) {Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
            for (Method method : methods) {
                if (introductionAwareMethodMatcher != null ?
                        introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
                        methodMatcher.matches(method, targetClass)) {return true;}
            }
        }

        return false;
    }

具体的匹配比较复杂,在 SignaturePattern 中的 matchesExactlyMethod 中对代理的办法做了匹配。

    private FuzzyBoolean matchesExactlyMethod(JoinPointSignature aMethod, World world, boolean subjectMatch) {if (parametersCannotMatch(aMethod)) {// System.err.println("Parameter types pattern" + parameterTypes + "pcount:" + aMethod.getParameterTypes().length);
            return FuzzyBoolean.NO;
        }
        // OPTIMIZE only for exact match do the pattern match now? Otherwise defer it until other fast checks complete?
        if (!name.matches(aMethod.getName())) {return FuzzyBoolean.NO;}
        // Check the throws pattern
        if (subjectMatch && !throwsPattern.matches(aMethod.getExceptions(), world)) {return FuzzyBoolean.NO;}

        // '*' trivially matches everything, no need to check further
        if (!declaringType.isStar()) {if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) {return FuzzyBoolean.MAYBE;}
        }

        // '*' would match any return value
        if (!returnType.isStar()) {boolean b = returnType.isBangVoid();
            if (b) {String s = aMethod.getReturnType().getSignature();
                if (s.length() == 1 && s.charAt(0) == 'V') {
                    // it is void, so not a match
                    return FuzzyBoolean.NO;
                }
            } else {if (returnType.isVoid()) {String s = aMethod.getReturnType().getSignature();
                    if (s.length() != 1 || s.charAt(0) != 'V') {
                        // it is not void, so not a match
                        return FuzzyBoolean.NO;
                    }
                } else {if (!returnType.matchesStatically(aMethod.getReturnType().resolve(world))) {
                        // looking bad, but there might be parameterization to consider...
                        if (!returnType.matchesStatically(aMethod.getGenericReturnType().resolve(world))) {
                            // ok, it's bad.
                            return FuzzyBoolean.MAYBE;
                        }
                    }
                }
            }
        }

        // The most simple case: pattern is (..) will match anything
        if (parameterTypes.size() == 1 && parameterTypes.get(0).isEllipsis()) {return FuzzyBoolean.YES;}

        if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) {return FuzzyBoolean.NO;}

        // OPTIMIZE both resolution of these types and their annotations should be deferred - just pass down a world and do it lower
        // down
        // ResolvedType[] resolvedParameters = world.resolve(aMethod.getParameterTypes());

        ResolvableTypeList rtl = new ResolvableTypeList(world, aMethod.getParameterTypes());
        // Only fetch the parameter annotations if the pointcut is going to be matching on them
        ResolvedType[][] parameterAnnotationTypes = null;
        if (isMatchingParameterAnnotations()) {parameterAnnotationTypes = aMethod.getParameterAnnotationTypes();
            if (parameterAnnotationTypes != null && parameterAnnotationTypes.length == 0) {parameterAnnotationTypes = null;}
        }

        if (!parameterTypes.matches(rtl, TypePattern.STATIC, parameterAnnotationTypes).alwaysTrue()) {
            // It could still be a match based on the generic sig parameter types of a parameterized type
            if (!parameterTypes.matches(new ResolvableTypeList(world, aMethod.getGenericParameterTypes()), TypePattern.STATIC,
                    parameterAnnotationTypes).alwaysTrue()) {
                return FuzzyBoolean.MAYBE;
                // It could STILL be a match based on the erasure of the parameter types??
                // to be determined via test cases...
            }
        }

        // check that varargs specifications match
        if (!matchesVarArgs(aMethod, world)) {return FuzzyBoolean.MAYBE;}

        // passed all the guards..
        return FuzzyBoolean.YES;
    }

获取到 aop 的拦挡办法之后调用 createProxy 办法创立代理类:

    protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
            @Nullable Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);

        if (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);
            }
            else {evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);
        }

        return proxyFactory.getProxy(getProxyClassLoader());
    }

持续跟进 getProxy 会进入到 DefaultProsyFactory 的 createAopProxy 办法,这里能够看到应用 jdk 动静代理还是应用 cglib 作为动静代理的判断条件

    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class:" +
                        "Either an interface or a target is required for proxy creation.");
            }
            if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);
            }
            return new ObjenesisCglibAopProxy(config);
        }
        else {return new JdkDynamicAopProxy(config);
        }
    }

动静代理的调用,这里以 cglib 做示例:当执行被代理对象的业务办法时,会执行 CglibAopProxy 的 intercept 办法:

            Object oldProxy = null;
            boolean setProxyContext = false;
            Object target = null;
            TargetSource targetSource = this.advised.getTargetSource();
            try {if (this.advised.exposeProxy) {
                    // Make invocation available if necessary.
                    oldProxy = AopContext.setCurrentProxy(proxy);
                    setProxyContext = true;
                }
                // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
                target = targetSource.getTarget();
                Class<?> targetClass = (target != null ? target.getClass() : null);
                List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                Object retVal;
                // Check whether we only have one InvokerInterceptor: that is,
                // no real advice, but just reflective invocation of the target.
                if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
                    // We can skip creating a MethodInvocation: just invoke the target directly.
                    // Note that the final invoker must be an InvokerInterceptor, so we know
                    // it does nothing but a reflective operation on the target, and no hot
                    // swapping or fancy proxying.
                    Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
                    retVal = methodProxy.invoke(target, argsToUse);
                }
                else {
                    // We need to create a method invocation...
                    retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}
                retVal = processReturnType(proxy, target, method, retVal);
                return retVal;
            }
            finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);
                }
                if (setProxyContext) {
                    // Restore old proxy.
                    AopContext.setCurrentProxy(oldProxy);
                }
            }
        }

这里的 getInterceptorsAndDynamicInterceptionAdvice 办法通过 Advice 获取到对应测加强办法,如果缓存中没有 CglibMethodInvocation 的对象的话,就 new 了一个并执行他的 proceed 办法。跟进进入 ReflectiveMethodInvocation 的 proceed 办法。

public Object proceed() throws Throwable {
        // We start with an index of -1 and increment early.
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();
        }

        Object interceptorOrInterceptionAdvice =
                this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
        if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
            // Evaluate dynamic method matcher here: static part will already have
            // been evaluated and found to match.
            InterceptorAndDynamicMethodMatcher dm =
                    (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
            Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
            if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {return dm.interceptor.invoke(this);
            }
            else {
                // Dynamic matching failed.
                // Skip this interceptor and invoke the next in the chain.
                return proceed();}
        }
        else {
            // It's an interceptor, so we just invoke it: The pointcut will have
            // been evaluated statically before this object was constructed.
            return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
        }
    }

这里的 currentInterceptorIndex 记录加强办法的索引,从 - 1 开始,没执行一个加强办法该值加 1,加强办法执行之后持续调用这个 proceed 办法,直到最初一个加强办法被执行,之后执行被代理办法。然而对于 After 告诉类型的加强办法并没有马上执行,而是写在了 finally 块中:

退出移动版