五、浅析Spring AOP(源码分析)

103 阅读14分钟

浅析Spring系列

一、浅析Spring启动流程

二、浅析Spring Bean的生命周期

三、浅析Spring循环依赖

四、浅析Spring事件

五、浅析Spring AOP

六、浅析Spring MVC


1. AOP概念与Spring AOP

1.1 AOP的概念

来自AOP官方文档:docs.spring.io/spring-fram…

英文水平有限,有些直接用英文比较准确。

Aspect:A modularization of a concern that cuts across multiple classes。例如:事务管理是一个好的横切关注点。

Join point:A point during the execution of a program。比如方法的执行,异常的处理。在Spring中,一般代表方法的执行。Spring AOP仅支持方法执行的join point

Advice:Action taken by an aspect at a particular join point。包括"around", "before", and "after" 三种advice。Spring中将advice类似拦截器,并且join point中维护了一系列的拦截器。

Pointcut:A predicate that matches join points. 

Introduction: Declaring additional methods or fields on behalf of a type.

Target object: An object being advised by one or more aspects

AOP proxy: An object created by the AOP framework in order to implement the aspect contracts。在Spring中,AOP proxy是JDK动态代理或者CGLIB代理。

Weaving: linking aspects with other application types or objects to create an advised object. 可以在编译时(如AspcetJ编译器)、加载时以及运用时,Spring AOP的Weaving就是在运行时。

1.2 Spring AOP的目标

docs.spring.io/spring-fram…

不是为了提供完整的AOP实现(比如仅支持方法的join point),而是旨在和Spring IOC结合解决通用问题。

1.3 Spring AOP和AspectJ关系

docs.spring.io/spring-fram…

Spring解释和AspectJ相同的注解,使用AspectJ提供的库进行切入点解析和匹配。在AOP运行时,仍然是纯Spring AOP,不会依赖AspectJ的编译器或者织入器。

2. 动态代理例子

Spring AOP底层的核心还是使用JDK动态代理或者CGLIB代理,所以理解这两种代理的使用,有助于我们理解源码。Spring也只是在此基础上增加了IOC和AspectJ的整合而已。

public interface IEchoService {
    void echo(String str);
}
public class MyEchoService implements IEchoService {
    @Override
    public void echo(String str) {
       System.out.println(str);
    }
}

2.1 JDK动态代理

JDK动态代理的核心是通过Proxy.newProxyInstance方法,拦截逻辑在InvocationHandler

public class JdkDynamicProxyDemo {

    public static void main(String[] args) {

       MyEchoService echoServiceImpl = new MyEchoService();

       IEchoService echoService = (IEchoService)Proxy.newProxyInstance(echoServiceImpl.getClass().getClassLoader(),
             echoServiceImpl.getClass().getInterfaces(), new InvocationHandler() {
          @Override
          public Object invoke(Object object, Method method, Object[] args) throws Throwable {

             System.out.println("jdk proxy");
             method.invoke(echoServiceImpl,args);
             return null;
          }
       });

       echoService.echo("hello");
       //output:
       //jdk proxy
       //hello
    }
}

2.2 CGLIB代理

CGLIB的核心是通过api,设置一些参数,然后创建代理对象。拦截函数在Callback接口,一般会使用子接口MethodInterceptor。

public class CglibProxyDemo {

    public static void main(String[] args) {
       Enhancer enhancer = new Enhancer();
       //设置目标类
       enhancer.setSuperclass(MyEchoService.class);
       //设置拦截函数
       enhancer.setCallback(new MethodInterceptor() {
          /**
           *
           * @param o  表示被代理的类
           * @param method 拦截的方法
           * @param objects 参数列表
           * @param methodProxy 拦截方法的代理,invokeSuper方法表示对被代理对象的方法的调用
           * @return 执行结果
           * @throws Throwable
           */
          @Override
          public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
             System.out.println("cglib proxy");
             //不能用invoke,会进入死循环;method.invoke执行的是子类的方法(也就是CGLIB生成的子类的方法k)
             methodProxy.invokeSuper(o, objects);
             return "";
          }
       });
       //创建代理类
       MyEchoService echoService = (MyEchoService) enhancer.create();

       echoService.echo("hello");

       //output:
       //cglib proxy
       //hello
    }
}

2.3 Spring使用AspectJ代理

在Spring AOP中,常用的是AspectJ的方式,以下是使用的例子。后续的源码分析中,也是基于此基础进行分析,其中拦截主要分析BeforeAdvice。

@Configuration
@EnableAspectJAutoProxy
public class AopDemo {

    public static void main(String[] args) {

       AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
       context.register(AopDemo.class);
       context.refresh();
       IEchoService echoService = context.getBean(IEchoService.class);
       echoService.echo("hello");
       //output:
       //before AspectJ
       //hello

       context.close();
    }

    @Bean
    public MyEchoService myEchoService(){
       return new MyEchoService();
    }
    @Bean
    public AspectConfig aspectConfig(){
       return new AspectConfig();
    }
}
@Aspect
public class AspectConfig {
    @Pointcut("execution(* com.spring.demo.MyEchoService.echo(..))")
    public void pointCut(){
    }
    @Before("pointCut()")
    public void before(){
       System.out.println("before AspectJ");
    }
    public void emptyMethod(){
    }
}

3. Spring AOP流程分析

源码分析主要分析Spring AOP对于AspectJ的整合,以及IOC的整合。主要分析流程,建议可以代码debug跟踪一下,比较容易理解。本章节会从@EnableAspectJAutoProxy注解作为入口,然后分析如何代理bean,再分析如何拦截Bean。

3.1 @EnableAspectJAutoProxy

从注解上发现会有@Import注解,AspectJAutoProxyRegistrar类实现了ImportBeanDefinitionRegistrar接口,会在IOC容器启动的过程中调用registerBeanDefinitions方法。而调用ImportBeanDefinitionRegistrar接口,在Spring启动阶段中的处理BeanFactoryPostProcessor阶段。

@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;

}

AspectJAutoProxyRegistrar的registerBeanDefinitions方法会注入AOP相关的Bean(BeanPostProssor)注入到IOC容器中,并且会把@EnableAspectJAutoProxy注解的值给运用起来。

//AspectJAutoProxyRegistrar#registerBeanDefinitions
public void registerBeanDefinitions(
      AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

   //注册AnnotationAwareAspectJAutoProxyCreator到IOC容器
   AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

   AnnotationAttributes enableAspectJAutoProxy =
         AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
   if (enableAspectJAutoProxy != null) {
      if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
         AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
      }
      if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
         AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
      }
   }
}

AopConfigUtils里会注册AnnotationAwareAspectJAutoProxyCreator,这个类实现了BeanPostProcessor接口。bean创建的过程中会调用BeanPostProcessor接口的方法。

//AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
      BeanDefinitionRegistry registry, @Nullable Object source) {

   return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

这里会把AnnotationAwareAspectJAutoProxyCreator封装成BeanDefinition。等到Spring启动阶段中的BeanPostProcessor处理阶段时,会被实例化和初始化。

private static BeanDefinition registerOrEscalateApcAsRequired(
      Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

   RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
   beanDefinition.setSource(source);
   beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
   registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
   return beanDefinition;
}

3.2 代理Bean

AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口,所以Bean在创建的过程中会调用,把Bean给代理了。主要入口在初始化完成后操作。

//AbstractAutoProxyCreator#postProcessAfterInitialization
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的逻辑如下,首先会判断,Bean是否需要代理,如果不用代理直接返回。然后回查找符合这个Bean的Advisor,如果找到了则进对这个Bean进行代理。主要逻辑有两大部分:查找符合的Advisor;对Bean进行创建代理。

//AbstractAutoProxyCreator#wrapIfNecessary
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;
}

3.2.1 查找Advisor

getAdvicesAndAdvisorsForBean是父类的抽象方法,子类AbstractAdvisorAutoProxyCreator会调用findEligibleAdvisors方法,逻辑如下

//AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      //会根据@Order等注解进行排序
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

而findCandidateAdvisors方法,在AnnotationAwareAspectJAutoProxyCreator会进行重写,内部实际会调用BeanFactoryAspectJAdvisorsBuilder的buildAspectJAdvisors方法

//AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
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;
}

在buildAspectJAdvisors方法中,主要会判断是否有@Aspect注解,然后调用advisorFactory的getAdvisors方法获取整个Advisor,并且会把结果缓存起来。advisorFactory的实现类实际就ReflectiveAspectJAdvisorFactory

//BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
public List<Advisor> buildAspectJAdvisors() {
    //...
    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;
        }
        //判断是否有Aspect注解,并且不是Ajc编译的(字段前缀不是ajc$)
        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);
            }
        }
    }
    //...
}

在getAdvisors方法中,首先会找AdvisorMethod,然后再获取Advisor

//ReflectiveAspectJAdvisorFactory#getAdvisors
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
   //...

   // 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)) {
      Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
      if (advisor != null) {
         advisors.add(advisor);
      }
   }

   //...
   return advisors;
}

在getAdvisorMethods方法中,会返回除了@Pointcut标记的方法。

//ReflectiveAspectJAdvisorFactory#getAdvisorMethods
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
   final List<Method> methods = new ArrayList<>();
   ReflectionUtils.doWithMethods(aspectClass, method -> {
      // Exclude pointcuts
      if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
         methods.add(method);
      }
   }, ReflectionUtils.USER_DECLARED_METHODS);
   if (methods.size() > 1) {
      methods.sort(METHOD_COMPARATOR);
   }
   return methods;
}

在getAdvisor方法中,会先获取PointCut,然后封装成一个Advisor。

//ReflectiveAspectJAdvisorFactory#getAdvisor
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);
}

在获取PpintCut方法中,首先会查找AspectJ注解,也就是@Before、@Around等注解,内部实现通过for循环查找,有找到就返回,然后创建AspectJExpressionPointcut对象,设置expression,此时如果我们直接引用了pointcut方法,这里还没有解析。例如:@Before("pointCut()"),此处的expression="pointCut()"。

//ReflectiveAspectJAdvisorFactory#getPointcut
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
   AspectJAnnotation<?> aspectJAnnotation =
         AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
   if (aspectJAnnotation == null) {
      return null;
   }

   AspectJExpressionPointcut ajexp =
         new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
   ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
   if (this.beanFactory != null) {
      ajexp.setBeanFactory(this.beanFactory);
   }
   return ajexp;
}

获取的AspectJExpressionPointcut最后会封装成Advisor,实现类就是InstantiationModelAwarePointcutAdvisorImpl,该类也实现了PointcutAdvisor。Advisor接口有个方法是获取Advice,该接口是切面的逻辑,看下如何返回不同类型的Advce,也就是对应不同的注解,如@Before,@Around。

内部实际会调用aspectJAdvisorFactory获取Advice,而aspectJAdvisorFactory就是ReflectiveAspectJAdvisorFactory。

//InstantiationModelAwarePointcutAdvisorImpl#getAdvice
public synchronized Advice getAdvice() {
   if (this.instantiatedAdvice == null) {
      this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
   }
   return this.instantiatedAdvice;
}
//InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
   Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
         this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
   return (advice != null ? advice : EMPTY_ADVICE);
}

在获取Advice逻辑中,可以发现是根据注解来,例如:Before注解,则返回AspectJMethodBeforeAdvice。

//ReflectiveAspectJAdvisorFactory#getAdvice
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
      MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

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

   //...

   return springAdvice;
}

3.2.2 过滤Advisor

前面已经找出来所有的Advisor,现在要看下哪些Advisor适合当前的Bean。

//AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(
      List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

   ProxyCreationContext.setCurrentProxiedBeanName(beanName);
   try {
      return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
   }
   finally {
      ProxyCreationContext.setCurrentProxiedBeanName(null);
   }
}

在findAdvisorsThatCanApply方法中,核心逻辑还是canApply方法中

//AopUtils#findAdvisorsThatCanApply
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
   if (candidateAdvisors.isEmpty()) {
      return candidateAdvisors;
   }
   List<Advisor> eligibleAdvisors = new ArrayList<>();
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
         eligibleAdvisors.add(candidate);
      }
   }
   boolean hasIntroductions = !eligibleAdvisors.isEmpty();
   for (Advisor candidate : candidateAdvisors) {
      if (candidate instanceof IntroductionAdvisor) {
         // already processed
         continue;
      }
      //核心判断逻辑
      if (canApply(candidate, clazz, hasIntroductions)) {
         eligibleAdvisors.add(candidate);
      }
   }
   return eligibleAdvisors;
}

内部实际上会在判断Advisor的类型,我们知道的Advisor是PointcutAdvisor,而且由前面得知,PointcutAdvisor的实现类是AspectJExpressionPointcut。

//AopUtils#canApply
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;
   }
}

在canApply内部,实际上会获取PointCut的MethodMatcher,获取Bean的所有方法(包括父类接口方法),然后遍历进行匹配,如果能匹配上就认为是符合的。

AspectJExpressionPointcut内部实际上也自己实现了ClassFilter和MethodMatcher接口,所以matches逻辑,都在AspectJExpressionPointcut内部实现。而内部则会通过获取PointcutExpression,然后进行判断方法是否符合@Pointcut注解。PointcutExpression实际上是由AspectJ框架提供的,这也应征了Spring AOP所描述的"Spring interprets the same annotations as AspectJ 5, using a library supplied by AspectJ for pointcut parsing and matching. The AOP runtime is still pure Spring AOP, though, and there is no dependency on the AspectJ compiler or weaver."

docs.spring.io/spring-fram…

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

3.2.3 创建代理对象

假设已经找到了合适的Advisor,现在是时候创建代理对象了。先会构建Advisor,因为我们从参数列表可以发现,虽然前面获取到了Advisor对象,但是参数实际上是Object的,可能是Spring为了更通用。所以对于不是Advisor的对象,会在封装成Advisor,最后会利用ProxyFactory创建代理对象

//AbstractAutoProxyCreator#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
   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内部会调用createAopProxy方法获取AopProxyFactory,然后调用getProxy代理对象,而返回的实际就是DefaultAopProxyFactory。

//ProxyFactory#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
   return createAopProxy().getProxy(classLoader);
}
//ProxyFactory#createAopProxy
protected final synchronized AopProxy createAopProxy() {
   if (!this.active) {
      activate();
   }
   return getAopProxyFactory().createAopProxy(this);
}
//ProxyFactory#getAopProxyFactory
public AopProxyFactory getAopProxyFactory() {
   return this.aopProxyFactory;
}
//ProxyFactory
public ProxyCreatorSupport() {
   this.aopProxyFactory = new DefaultAopProxyFactory();
}

在获取AopProxy对象的内部逻辑中,会判断是使用JDK动态代理,还是CGLIB代理,逻辑如下代码所示。现在简单做个总结:

  • 如果目标对象实现了接口,默认会采用JDK动态代理实现AOP。
  • 如果目标对象实现了接口, 可以强制使用CGLIB实现AOP。@EnableAspectJAutoProxy注解的proxyTargetClass设置为true或者xml配置的proxy-target-class设置为true。
  • 如果目标对象没有实现接口,必须采用CGLIB实现AOP。

JDK动态代理和CGLIB字节码生成的区别如下:

  • JDK动态代理只能对实现了接口的类生成代理(底层逻辑有判断必须是接口才能代理),而不能针对类。
  • CGLIB是针对类实现代理,底层逻辑是继承,对指定类生成一个子类,覆盖其中的方法,所以要代理的方法不要声明为final或private。
//DefaultAopProxyFactory#createAopProxy
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.");
     }
      //代理对象是个接口 || 或者已经是JDK动态代理
     if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
        return new JdkDynamicAopProxy(config);
     }
     return new ObjenesisCglibAopProxy(config);
  }
  else {
     return new JdkDynamicAopProxy(config);
  }
}

先看下JdkDynamicAopProxy获取代理对象的逻辑,核心就是调用Proxy.newProxyInstance方法,并且JdkDynamicAopProxy有实现InvocationHandler接口,也就是拦截逻辑就在JdkDynamicAopProxy中。

//JdkDynamicAopProxy#getProxy
public Object getProxy() {
   return getProxy(ClassUtils.getDefaultClassLoader());
}

//JdkDynamicAopProxy#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isTraceEnabled()) {
      logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
   }
   Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
   findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
   return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

再看下ObjenesisCglibAopProxy,继承了CglibAopProxy,getProxy实际就是在CglibAopProxy里。逻辑上也是调用CGLIB的api,然后创建代理对象。CGLIB拦截的逻辑就在Callback接口上,在Spring AOP上,具体拦截逻辑就在DynamicAdvisedInterceptor上。

//CglibAopProxy#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
    //...
    // Configure CGLIB Enhancer...
    Enhancer enhancer = createEnhancer();
    if (classLoader != null) {
        enhancer.setClassLoader(classLoader);
        if (classLoader instanceof SmartClassLoader &&
                       ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
            enhancer.setUseCache(false);
        }
    }
    enhancer.setSuperclass(proxySuperClass);
    enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
    enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
    enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
    Callback[] callbacks = getCallbacks(rootClass);
    Class<?>[] types = new Class<?>[callbacks.length];
    for (int x = 0; x < types.length; x++) {
        types[x] = callbacks[x].getClass();
    }
    // fixedInterceptorMap only populated at this point, after getCallbacks call above
    enhancer.setCallbackFilter(new ProxyCallbackFilter(
                this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
    enhancer.setCallbackTypes(types);
    // Generate the proxy class and create a proxy instance.
    return createProxyClassAndInstance(enhancer, callbacks);
    // ...
}

3.3 拦截Bean

3.3.1 JdkDynamicAopProxy

拦截的核心,在于创建执行链,然后通过封装成MethodInvocation进行调用。获取拦截链的方法实际上会通过AdvisorChainFactory接口的getInterceptorsAndDynamicInterceptionAdvice方法获取,AdvisorChainFactory的默认实现类为DefaultAdvisorChainFactory

//JdkDynamicAopProxy#invoke
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);


// We need to create a method invocation...
MethodInvocation invocation =
      new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();

在DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法中,核心逻辑如下:从前面得知我们的Advisor实际上PointcutAdvisor,会走一下逻辑,通过AdvisorAdapterRegistry获取MethodInterceptor接口。AdvisorAdapterRegistry的默认实现为DefaultAdvisorAdapterRegistry。

//DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match = mm.matches(method, actualClass);
//...
if (match) {
    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
}

获取拦截器的逻辑为:从AdvisorAdapter列表中便利,如果支持的Advise就进行转换,默认的AdvisorAdapter有MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter和ThrowsAdviceAdapter。

//DefaultAdvisorAdapterRegistry#getInterceptors
for (AdvisorAdapter adapter : this.adapters) {
    if (adapter.supportsAdvice(advice)) {
       interceptors.add(adapter.getInterceptor(advisor));
    }
}
//DefaultAdvisorAdapterRegistry
public DefaultAdvisorAdapterRegistry() {
    registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
    registerAdvisorAdapter(new AfterReturningAdviceAdapter());
    registerAdvisorAdapter(new ThrowsAdviceAdapter());
}

可以看下MethodBeforeAdviceAdapter 的逻辑,就是MethodBeforeAdvice时,封装成MethodBeforeAdviceInterceptor(实现了MethodInterceptor接口)进行返回。后续会有接口进行调用MethodInterceptor接口的方法。

//MethodBeforeAdviceAdapter
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

    @Override
    public boolean supportsAdvice(Advice advice) {
       return (advice instanceof MethodBeforeAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
       MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
       return new MethodBeforeAdviceInterceptor(advice);
    }

}

在proceed中就是通过递归调用的方式进行MethodInterceptor的拦截,当MethodInterceptor执行完后,最后会执行invokeJoinpoint方法,也就是会调用真正要调用的方法。我们从前面得知MethodInterceptor实际就是MethodBeforeAdviceInterceptor,这里的invoke参数为this(ReflectiveMethodInvocation实现了MethodInvocation接口,MethodInvocation接口继承了Joinpoint接口,Joinpoint提供了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);

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

在MethodBeforeAdviceInterceptor的逻辑中,会先调用advice的before接口,然后调用MethodInvocation的proceed,其实就是会回到ReflectiveMethodInvocation的proceed方法中

//MethodBeforeAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    return mi.proceed();
}

这里的advice其实就是AspectJMethodBeforeAdvice,内部实际上调用父类的方法。会通过反射进行调用拦截的方法。aspectJAdviceMethod就是拦截的方法,this.aspectInstanceFactory.getAspectInstance()就是定义拦截方法的类。到此处我们了解到了拦截方法的执行。

//AbstractAspectJAdvice#invokeAdviceMethodWithGivenArgs
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {

    try {
       ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
       // TODO AopUtils.invokeJoinpointUsingReflection
       return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
    }
    
}

回到ReflectiveMethodInvocation的invokeJoinpoint,其实就是调用真正要调用的方法,内部会通过AopUtils工具类提供的方法执行。逻辑其实也很简单,就是通过反射进行方法调用。

public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
       throws Throwable {

    // Use reflection to invoke the method.
    try {
       ReflectionUtils.makeAccessible(method);
       return method.invoke(target, args);
    }
  	//...
}

3.3.2 DynamicAdvisedInterceptor

DynamicAdvisedInterceptor的逻辑和JdkDynamicAopProxy的逻辑类似,这里就不重复说明。

4. 参考资料

  1. Spring 源码分支5.1.x
  2. 《Spring 源码解析》