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 块中:

image


jiao个朋友
4 声望0 粉丝