Spring AOP(二) 修饰者模式、JDK Proxy以及源码分析

在上边一篇文章中我们介绍了Spring AOP的基本概念,今天我们就来学习一下与AOP实现相关的修饰者模式和Java Proxy相关的原理,以及AOP的源码分析。

修饰者模式

Java设计模式中的修饰者模式能动态地给目标对象增加额外的职责(Responsibility)。它使用组合(object composition),即将目标对象作为修饰者对象(代理)的成员变量,由修饰者对象决定调用目标对象的时机和调用前后所要增强的行为。
装饰模式包含如下组成部分:

  • Component: 抽象构件,也就是目标对象所实现的接口,有operation函数
  • ConcreteComponent: 具体构件,也就是目标对象的类
  • Decorator: 抽象装饰类,也实现了抽象构件接口,也就是目标类和装饰类都实现了相同的接口
  • ConcreteDecorator: 具体装饰类,其中addBeavior函数就是增强的行为,装饰类可以自己决定addBeavior函数和目标对象函数operation函数的调用时机。
    【加群】:857565362  修饰者模式的类图
    修饰者模式调用的时序图如下图所示。程序首先创建目标对象,然后创建修饰者对象,并将目标对象传入作为其成员变量。当程序调用修饰者对象的operation函数时,修饰者对象会先调用目标对象的operation函数,然后再调用自己的addBehavior函数。这就是类似于AOP的后置增强器,在目标对象的行为之后添加新的行为。
    【加群】:857565362 修饰者模式的时序图
    Spring AOP的实现原理和修饰者模式类似。在上一篇文章中说到AOP的动态代理有两种实现方式,分别是JDK Proxy和cglib。
    如下图所示,JDK Proxy的类结构和上文中修饰者的类图结构类似,都是代理对象和目标对象都实现相同的接口,代理对象持有目标对象和切面对象,并且决定目标函数和切面增强函数的调用时机。
    而cglib的实现略有不同,它没有实现实现相同接口,而是代理对象继承目标对象类。
    【加群】:857565362  两种动态代理的对标
    本文后续就讲解一下JDK Proxy的相关源码分析。

JDK Proxy

JDK提供了Proxy类来实现动态代理的,可通过它的newProxyInstance函数来获得代理对象。JDK还提供了InvocationHandler类,代理对象的函数被调用时,会调用它的invoke函数,程序员可以在其中实现所需的逻辑。
JDK Proxy的基本语法如下所示。先构造一个InvocationHandler的实现类,然后调用Proxy的newProxyInstance函数生成代理对象,传入类加载器,目标对象的接口和自定义的InvocationHandler实例。

public class CustomInvocationHandler implements InvocationHandler {
    private Object target;
    
      public CustomInvocationHandler(Object target) {
        this.target = target;
    }
       
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before invocation");
        Object retVal = method.invoke(target, args);
        System.out.println("After invocation");
        return retVal;
}
}
        CustomInvocationHandler customInvocationHandler = new CustomInvocationHandler(
        helloWord);//通过Proxy.newProxyInstance生成代理对象
ProxyTest proxy = (ProxyTest) Proxy.newProxyInstance(
        ProxyTest.class.getClassLoader(),
       proxyObj.getClass().getInterfaces(), customInvocationHandler);

生成代理对象
我们首先来看一下Proxy的newProxyInstance函数。newProxyInstance函数的逻辑大致如下:

  • 首先根据传入的目标对象接口动态生成代理类
  • 然后获取代理类的构造函数实例
  • 最后将InvocationHandler作为参数通过反射调用构造函数实例,生成代理类对象。
    具体源码如下所示。
public static Object newProxyInstance(ClassLoader loader,
                                        Class<?>[] interfaces,
                                        InvocationHandler h)
    throws IllegalArgumentException{
                final Class<?>[] intfs = interfaces.clone();
    final SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
    }
    // 1 动态生成代理对象的类
    Class<?> cl = getProxyClass0(loader, intfs);
               // ... 代码省略,下边代码其实是在try catch中的
    if (sm != null) {
        checkNewProxyPermission(Reflection.getCallerClass(), cl);
    }
    // 2 获取代理类的构造函数
    final Constructor<?> cons = cl.getConstructor(constructorParams);
    final InvocationHandler ih = h;
    if (!Modifier.isPublic(cl.getModifiers())) {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                cons.setAccessible(true);
                return null;
            }
        });
    }
    // 3调用构造函数,传入InvocationHandler对象
    return cons.newInstance(new Object[]{h});}
 getProxyClass0函数的源码如下所示,通过代理类缓存获取代理类信息,如果不存在则会生成代理类。
// 生成代理类private static Class<?> getProxyClass0(ClassLoader loader,
                                        Class<?>... interfaces) {
    if (interfaces.length > 65535) {
        throw new IllegalArgumentException("interface limit exceeded");
    }
            // 如果已经有Proxy类的缓存则直接返回,否则要进行创建
    return proxyClassCache.get(loader, interfaces);}

生成代理类
JDK Proxy通过ProxyClassFactory生成代理类。其apply函数大致逻辑如下:

  • 校验接口是否符合规范· 生成代理类的名称和包名
  • 生成代理类字节码
  • 根据字节码生成代理类Class
// 生成代理类的工厂类
private static final class ProxyClassFactory
    implements BiFunction<ClassLoader, Class<?>[], Class<?>>{
    // 所有代理类名的前缀
    private static final String proxyClassNamePrefix = "$Proxy";
             // 生成唯一类名的原子Long对象
    private static final AtomicLong nextUniqueNumber = new AtomicLong();
                 @Override
    public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
                 Map<Class<?>, Boolean> interfaceSet = new
 IdentityHashMap<>(interfaces.length);
        for (Class<?> intf : interfaces) {
            // 通过loader找到接口对应的类信息。
            Class<?> interfaceClass = null;
            try {
                interfaceClass = Class.forName(intf.getName(), false, loader);
            } catch (ClassNotFoundException e) {
            }
            if (interfaceClass != intf) {
                throw new IllegalArgumentException(
                    intf + " is not visible from class loader");
            }
            // 判断找出来的类确实是一个接口
            if (!interfaceClass.isInterface()) {
                throw new IllegalArgumentException(
                    interfaceClass.getName() + " is not an interface");
            }
            // 判断接口是否重复
            if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                throw new IllegalArgumentException(
                    "repeated interface: " + interfaceClass.getName());
            }
        }
        // 代理类的包路径
        String proxyPkg = null;
        int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
                  // 记录非公开的代理接口,以便于生成的代理类和原来的类在同一个路径下。
         for (Class<?> intf : interfaces) {
            int flags = intf.getModifiers();
            if (!Modifier.isPublic(flags)) {
                accessFlags = Modifier.FINAL;
                String name = intf.getName();
                int n = name.lastIndexOf('.');
                String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                if (proxyPkg == null) {
                    proxyPkg = pkg;
                } else if (!pkg.equals(proxyPkg)) {
                    throw new IllegalArgumentException(
                        "non-public interfaces from different packages");
                }
            }
        }
        // 如果没有非公开的Proxy接口,使用com.sun.proxy报名
        if (proxyPkg == null) {
            proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
        }
                  long num = nextUniqueNumber.getAndIncrement();
        // 默认情况下,代理类的完全限定名为:com.sun.proxy.$Proxy0,$Proxy1……依次递增
          String proxyName = proxyPkg + proxyClassNamePrefix + num;
                 // 生成代理类字节码
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
            proxyName, interfaces, accessFlags);
        try {
            // 根据字节码返回相应的Class实例
            return defineClass0(loader, proxyName,
                                proxyClassFile, 0, proxyClassFile.length);
        } catch (ClassFormatError e) {
            throw new IllegalArgumentException(e.toString());
        }
}
}

其中关于字节码生成的部分逻辑我们就暂时不深入介绍了,感兴趣的同学可以自行研究。

$Proxy反编译

我们来看一下生成的代理类的反编译代码。代理类实现了Object的基础函数,比如toString、hasCode和equals,也实现了目标接口中定义的函数,比如说ProxyTest接口的test函数。
$Proxy中函数的实现都是直接调用了InvocationHandler的invoke函数。

public final class $Proxy0 extends Proxy
  implements ProxyTest // 会实现目标接口,但是由于集成了Proxy,所以无法再集成其他类{
  private static Method m1;
  private static Method m0;
  private static Method m3;
  private static Method m2;
  // 构造函数要传入一个InvocationHandler对象
  public $Proxy0(InvocationHandler paramInvocationHandler)
    throws
   {
    super(paramInvocationHandler);
  }
  // equal函数
  public final boolean equals(Object paramObject)
    throws 
  { 
     try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[]
 { paramObject })).booleanValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
    }
    throw new UndeclaredThrowableException(localThrowable);
  }
      public final int hashCode()
    throws
   {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
    }
    throw new UndeclaredThrowableException(localThrowable);
  }
  // test函数,也就是ProxyTest接口中定义的函数
  public final void test(String paramString)
    throws
   {
    try
    {
      // 调用InvocationHandler的invoke函数
      this.h.invoke(this, m3, new Object[] { paramString });
      return;
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
    }
    throw new UndeclaredThrowableException(localThrowable);
  }
           public final String toString()
    throws
   {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
    }
    throw new UndeclaredThrowableException(localThrowable);
  }
  // 获取各个函数的Method对象
  static
  {
    try
    {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m3 = Class.forName("com.proxy.test2.HelloTest").getMethod("say", new Class[] { Class.forName("java.lang.String") });
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
    }
    throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
  }
}

Spring AOP是Spring的两大基石之一,接下来是源码的解析。
从代码执行角度来看,Spring AOP的执行过程分为四大步骤:

  • 步骤一:Spring框架生成Advisor实例,可以是@Aspect,@Async等注解生成的实例,也可以是程序员自定义的AbstractAdvisor子类的实例.
  • 步骤二:Spring框架在目标实例初始化完成后,也就是使用BeanPostProcessor的postProcessAfterInitialization方法,根据Advisor实例中切入点Pointcut的定义,选择出适合该目标对象的Advisor实例。
  • 步骤三:Spring框架根据Advisor实例生成代理对象。
  • 步骤四:调用方法执行过程时,Spring框架执行Advisor实例的通知Advice逻辑。
    由于这四个步骤涉及的源码量较大,一篇文章无法直接完全讲解完,本篇文章只讲解第一步Advisor实例生成的源码分析。接下来我们就依次讲解一下后续步骤中比较关键的逻辑。
    Advisor类架构
    Spring中有大量的机制都是通过AOP实现的,比如说@Async的异步调用和@Transational。此外,用户也可以使用@Aspect注解定义切面或者直接继承AbstractPointcutAdvisor来提供切面逻辑。上述这些情况下,AOP都会生成对应的Advisor实例。
    我们先来看一下Advisor的相关类图。首先看一下org.aopalliance包下的类图。aopalliance是AOP组织下的公用包,用于AOP中方法增强和调用,相当于一个jsr标准,只有接口和异常,在AspectJ、Spring等AOP框架中使用。
    【加群】:857565362 aopallinace类图
    aopalliance定义了AOP的通知Advice和连接点Joinpoint接口,并且还有继承上述接口的MethodInterceptor和MethodInvocation。这两个类相信大家都很熟悉。
    然后我们来看一下Spring AOP中Advisor相关的类图。Advisor是Spring AOP独有的概念,比较重要的类有AbstractPointcutAdvisor和InstantiationModelAwarePointcutAdvisor。相关的讲解都在图中表明了,如果这张图中的概念和类同学们都熟识,那么对AOP的了解就已经很深入了。
    【加群】:857565362   Advisor相关类图
    获取所有Advisor实例
    AOP生成Advisor实例的函数入口是AbstractAdvisorAutoProxyCreator的findCandidateAdvisors函数。
// AbstractAdvisorAutoProxyCreator.java 找出当前所有的Advisorprotected List<Advisor> findCandidateAdvisors() {
    Assert.state(this.advisorRetrievalHelper != null, "No
     BeanFactoryAdvisorRetrievalHelper available");
    return this.advisorRetrievalHelper.findAdvisorBeans();}
    // AnnotationAwareAspectJAutoProxyCreator,是AbstractAdvisorAutoProxyCreator的子类@Overrideprotected List<Advisor> findCandidateAdvisors() {
    // 调用父类的findCandidateAdvisor函数,一般找出普通的直接
    // 继承Advisor接口的实例,比如说`@Async`所需的`AsyncAnnotationAdvisor`
    List<Advisor> advisors = super.findCandidateAdvisors();
    // 为AspectJ的切面构造Advisor,也就是说处理@Aspect修饰的类,生成上文中说的`InstantiationModelAwarePointcutAdvisor`实例
    if (this.aspectJAdvisorsBuilder != null) {
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    }return advisors;
}

相关的ProxyCreator也有一个类体系,不过太过繁杂,而且重要性不大,我们就先略过,直接将具体的类。由上边代码可知AbstractAdvisorAutoProxyCreator的findCandidateAdvisors函数是直接获取Spring容器中的Advisor实例,比如说AsyncAnnotationAdvisor实例,或者说我们自定义的AbstractPointcutAdvisor的子类实例。AdvisorRetrievalHelper的findAdvisorBeans函数通过BeanFactory的getBean获取了所有类型为Advisor的实例。
而AnnotationAwareAspectJAutoProxyCreator看其类名就可知,是与AspectJ相关的创建器,用来获取@Aspect定义的Advisor实例,也就是InstantiationModelAwarePointcutAdvisor实例。
接下去我们看一下BeanFactoryAspectJAdvisorsBuilder的buildAspectJAdvisors函数,它根据@Aspect修饰的切面实例生成对应的Advisor实例。

public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = this.aspectBeanNames;
    // 第一次初始化,synchronized加双次判断,和经典单例模式的写法一样。
    if (aspectNames == null) {
        synchronized (this) {
            aspectNames = this.aspectBeanNames;
            if (aspectNames == null) {
                // Spring源码并没有buildAspectJAdvisorsFirstly函数,为了方便理解添加。
                // 获取aspectNames,创建Advisor实例,并且存入aspectFactoryCache缓存 
               return buildAspectJAdvisorsFirstly(); 
           }
        }
    }
            if (aspectNames.isEmpty()) {
        return Collections.emptyList();
    }
    List<Advisor> advisors = new ArrayList<>();
    // 遍历aspectNames,依次获取对应的Advisor实例,或者是MetadataAwareAspectInstanceFactory生成的Advisor实例
    for (String aspectName : aspectNames) {
        List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
        // cache可以取到实例,该Advisor是单例的
        if (cachedAdvisors != null) {
            advisors.addAll(cachedAdvisors);
        }
        else {
            // 取得Advisor对应的工厂类实例,再次生成Advisor实例,该Advisor是多实例的。
            MetadataAwareAspectInstanceFactory factory =
 this.aspectFactoryCache.get(aspectName);
            advisors.addAll(this.advisorFactory.getAdvisors(factory));
        }
    }return advisors;
}

buildAspectJAdvisors函数执行时分为两种情况,第一个未初始化时,也就是aspectNames为null时,执行buildAspectJAdvisorsFirstly进行第一次初始化,在这一过程中生成切面名称列表aspectBeanNames和要返回的Advisor列表,并且将生成的Advisor实例放置到advisorsCache中。
第二种情况则是已经初始化后再次调用,遍历aspectNames,从advisorsCache取出对应的Advisor实例,或者从advisorsCache取出Advisor对应的工厂类对象,再次生成Advisor实例。

public List<Advisor> buildAspectJAdvisorsFirstly() {
    List<Advisor> advisors = new ArrayList<>();
    List<String> aspectNames = new ArrayList<>();
    // 调用BeanFactoryUtils获取所有bean的名称
    String[] beanNames =
 BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Object.class, true, false);
    for (String beanName : beanNames) {
        if (!isEligibleBean(beanName)) {
            continue;
        }
        // 获取对应名称的bean实例
        Class<?> beanType = this.beanFactory.getType(beanName);
        if (beanType == null) {
            continue;
        }
        /**
         * AbstractAspectJAdvisorFactory类的isAspect函数来判断是否为切面实例
         * 判断条件为是否被@Aspect修饰或者是由AspectJ编程而来。
         */
        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);
                // 获取一个切面中所有定义的Advisor实例。一个切面可以定义多个Advisor。
                List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);                
                // 单例模式,只需要将生成的Advisor添加到缓存
                if (this.beanFactory.isSingleton(beanName)) {
                    this.advisorsCache.put(beanName, classAdvisors);
                }
                // 多实例模式,需要保存工厂类,便于下一次再次生成Advisor实例。
                else {
                    this.aspectFactoryCache.put(beanName, factory);
                }
                advisors.addAll(classAdvisors);
            }
            else {
                MetadataAwareAspectInstanceFactory factory =
                        new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                this.aspectFactoryCache.put(beanName, factory);
                advisors.addAll(this.advisorFactory.getAdvisors(factory));
            }
        }
    }
    this.aspectBeanNames = aspectNames;return advisors;
}

buildAspectJAdvisorsFirstly函数的逻辑如下:

  • 首先使用BeanFactoryUtils获取了BeanFactory中所有的BeanName,然后进而使用BeanFactory获取所有的Bean实例。
  • 遍历Bean实例,通过ReflectiveAspectJAdvisorFactory的isAspect函数判断该实例是否为切面实例,也就是被@Aspect注解修饰的实例。
  • 如果是,则使用ReflectiveAspectJAdvisorFactory,根据切面实例的定义来生成对应的多个Advisor实例,并且将其加入到advisorsCache中。
    生成InstantiationModelAwarePointcutAdvisorImpl实例
    ReflectiveAspectJAdvisorFactory的getAdvisors函数会获取@Aspect修饰的实例中所有没有被@Pointcut修饰的方法,然后调用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;
    }
    // 生成Advisor实例
    return new
 InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
            this, aspectInstanceFactory, declarationOrderInAspect, aspectName);}
private AspectJExpressionPointcut getPointcut(Method
 candidateAdviceMethod, Class<?> candidateAspectClass) {
    // 获得该函数上@Pointcut, @Around, @Before, @After, @AfterReturning, @AfterThrowing注解的信息
    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;
}

getAdvisor函数就是根据作为参数传入的切面实例的方法上的注解来生成Advisor实例,也就是InstantiationModelAwarePointcutAdvisorImpl对象。依据方法上的切入点表达式生成AspectJExpressionPointcut。
我们都知道PointcutAdvisor实例中必然有一个Pointcut和Advice实例。修饰在方法上的注解包括:@Pointcut, @Around, @Before, @After, @AfterReturning和@AfterThrowing,所以InstantiationModelAwarePointcutAdvisorImpl会依据不同的不同的注解生成不同的Advice通知。

public
 InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
        Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
    // .... 省略成员变量的直接赋值
                // 单例模式时
    this.pointcut = this.declaredPointcut;
    this.lazy = false;
    // 按照注解解析 Advice
    this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);}

InstantiationModelAwarePointcutAdvisorImpl的构造函数中会生成对应的Pointcut和Advice。instantiateAdvice函数调用了ReflectiveAspectJAdvisorFactory的getAdvice函数。

// ReflectiveAspectJAdvisorFactorypublic Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
        MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
               Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
    validate(candidateAspectClass);
    // 获取 Advice 注解
    AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    if (aspectJAnnotation == null) {
        return null;
    }
             // 检查是否为AspectJ注解
    if (!isAspect(candidateAspectClass)) {
        throw new AopConfigException("Advice must be declared inside an aspect type: " +
                "Offending method '" + candidateAdviceMethod + "' in class [" +
                candidateAspectClass.getName() + "]");
    }
        AbstractAspectJAdvice springAdvice;
    // 按照注解类型生成相应的 Advice 实现类
    switch (aspectJAnnotation.getAnnotationType()) {
        case AtPointcut:
            if (logger.isDebugEnabled()) {
               logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
            }
            return null;
        case AtAround:
 // @Before 生成 AspectJMethodBeforeAdvice
            springAdvice = new AspectJAroundAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtBefore:
 // @After 生成 AspectJAfterAdvice
            springAdvice = new AspectJMethodBeforeAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfter: // @AfterReturning 生成 AspectJAfterAdvice
            springAdvice = new AspectJAfterAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            break;
        case AtAfterReturning:
 // @AfterThrowing 生成 AspectJAfterThrowingAdvice
            springAdvice = new AspectJAfterReturningAdvice(
                    candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
            AfterReturning afterReturningAnnotation = (AfterReturning)
 aspectJAnnotation.getAnnotation();
            if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                springAdvice.setReturningName(afterReturningAnnotation.returning());
            }
            break;
        case AtAfterThrowing:
 // @Around 生成 AspectJAroundAdvice
            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);
    }
 // 配置Advice
    springAdvice.setAspectName(aspectName);
    springAdvice.setDeclarationOrder(declarationOrder);
    // 获取方法的参数列表方法
    String[] argNames =
 this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
    if (argNames != null) {
        // 设置参数名称 
       springAdvice.setArgumentNamesFromStringArray(argNames); 
   }
    springAdvice.calculateArgumentBindings();
            return springAdvice;
}

至此,Spring AOP就获取了容器中所有的Advisor实例,下一步在每个实例初始化完成后,根据这些Advisor的Pointcut切入点进行筛选,获取合适的Advisor实例,并生成代理实例。
我这儿整理了比较全面的JAVA相关的面试资料,
需要领取面试资料的同学,请加群:473984645
在这里插入图片描述
获取更多学习资料,可以加群:473984645或扫描下方二维码
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值