Spring AOP源码深入分析

作者:程序员小潘 时间:2023-08-15 13:01:16 

1. 前言

Spring除了IOC和DI,还有另一个杀手锏功能——Spring AOP。AOP是一种面向切面的编程思想,它的关注点是横向的,不同于OOP的纵向。面向对象编程时,如果我们要给多个类引入同一个行为,唯一的方式就是使用继承,否则就要在这些类里面加入大量重复的代码,如此一来程序将不利于维护。于是,AOP横空出世,它弥补了OOP编程的弊端。Spring内部也有大量特性是通过AOP来实现的,比如我们熟知的数据库事务。

2. 术语

查看源码前,先了解一下AOP的相关术语。

连接点(Joinpoint)

Advice执行的位置,比如:方法前、方法后、发生异常时等等,Spring仅支持方法的连接点。

切点(Pointcut)

连接点的过滤条件,AOP通过切点定位到具体的连接点。

增强/通知(Advice)

应用在连接点的行为,增强的逻辑代码,分为:前置、后置、环绕、异常增强。

增强器(Advisor)

通知器由一个切点(Pointcut)和一个增强(Advice)组成。

切面(Aspect)

由切点(Pointcut)和增强(Advice)组成。

织入(Weaving)

将增强应用到目标连接点的过程,可以静态织入,也可以运行时织入。

目标(Target)

被增强的对象(方法)。

代理(Proxy)

向Target应用Advice之后创建的代理对象。

3. 示例

Spring AOP使用起来非常简单,这里提供一个小示例。

1、定义切面

@Aspect
@Component
public class MyAspectConfig {
   @Pointcut("execution(* com.javap.aop.*.*(..))")
   public void pointCut() {
   }
   /**
    * 每一个增强方法,都会被封装成Advisor对象
    *
    * @see Advisor
    */
   @Before("pointCut()")
   public void before() {
       System.err.println("before");
   }
   @After("pointCut()")
   public void after() {
       System.err.println("after");
   }
   @Around("pointCut()")
   public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
       System.err.println("Around before");
       Object result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
       System.err.println("Around after");
       return result;
   }
   @AfterReturning(value = "pointCut()", returning = "result")
   public void afterReturning(JoinPoint joinPoint, String result) throws Throwable {
       System.err.println("afterReturning: " + result);
   }
   @AfterThrowing(value = "pointCut()", throwing = "e")
   public void afterThrowing(Exception e) throws Throwable {
       System.err.println("afterThrowing: " + e.getMessage());
   }
}

2、定义bean,也就是需要被增强的目标对象

@Component
public class Person {
   public String say() {
       System.err.println("say...");
       return "aabbccdd";
   }
   /**
    * final方法,子类无法重写,因此不能被增强
    */
   public final void eat() {
       System.err.println("eat...");
   }
}

3、加上@EnableAspectJAutoProxy注解,就可以启用AOP了。

@Configuration
@ComponentScan("com.javap.aop")
@EnableAspectJAutoProxy
public class AopApplication {
   public static void main(String[] args) {
       ApplicationContext context = new AnnotationConfigApplicationContext(AopApplication.class);
       Person person = context.getBean(Person.class);
       person.say();
       person.eat();
   }
}

控制台输出:

Around before
before
say...
Around after
after
afterReturning: aabbccdd
eat...

4. @EnableAspectJAutoProxy

问题:为什么在启动类上,加上**@EnableAspectJAutoProxy**注解就可以开启AOP呢???

答案当然要在注解本身找了,该注解上有一个@Import注解,引入了AspectJAutoProxyRegistrar类。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* 是否强制使用类代理模式:CGLIB代理
*/
boolean proxyTargetClass() default false;
/**
* 是否暴露代理对象,以通过AopContext获取
*/
boolean exposeProxy() default false;
}

AspectJAutoProxyRegistrar类实现了Spring提供的ImportBeanDefinitionRegistrar接口并重写了registerBeanDefinitions()方法,如此一来Spring在启动时,就会触发AspectJAutoProxyRegistrar#registerBeanDefinitions()方法,该方法会向容器内注册一个特别重要的类AnnotationAwareAspectJAutoProxyCreator

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
   @Override
   public void registerBeanDefinitions(
           AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
       /**
        * 注册AnnotationAwareAspectJAutoProxyCreator类
        */
       AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
       // 获取注解信息
       AnnotationAttributes enableAspectJAutoProxy =
               AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
       if (enableAspectJAutoProxy != null) {
           /**
            * 将注解属性写入到BeanDefinition
            * proxyTargetClass:是否通过CGLIB类代理模式
            * exposeProxy:是否暴露代理类,以通过AopContext获取
            */
           if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
               AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
           }
           if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
               AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
           }
       }
   }
}

AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口,属于Spring的扩展点之一,Spring在实例化bean实例后,会触发该扩展点,对bean做扩展和增强,也就是返回织入了Advice后的代理对象。

Spring AOP源码深入分析

5. AbstractAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator既然实现了BeanPostProcessor接口,那么必然要重写postProcessAfterInitialization()方法来返回增强后的bean,重写方法在父类AbstractAutoProxyCreator里。

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
       Object cacheKey = getCacheKey(bean.getClass(), beanName);
       // 循环依赖,提前暴 * ean时,代理对象可能已经生成
       if (this.earlyProxyReferences.remove(cacheKey) != bean) {
           // 生成增强后的代理对象,如果有需要
           return wrapIfNecessary(bean, beanName, cacheKey);
       }
   }
   return bean;
}

Spring会调用wrapIfNecessary()方法来返回增强后的bean。**所有的bean都会被BeanPostProcessor处理,但并不是所有的bean都需要增强,Spring会根据切点表达式判断beanClass是否需要被增强。**这个判断过程是比较耗时的,因为要解析beanClass所有的方法去和切点表达式进行匹配,所以Spring加了一个Map缓存解析过的beanClass。

判断bean是否要增强也很简单,通过getAdvicesAndAdvisorsForBean()方法去解析能应用到beanClass的所有增强器Advisor,如果没有增强器可用于该beanClass,也就不需要增强,直接原样返回bean即可,否则基于Advisor去创建增强后的代理对象。

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))) {
       // 已经解析过beanClass,且判定为无需增强
       return bean;
   }
   if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
       // 无需增强
       this.advisedBeans.put(cacheKey, Boolean.FALSE);
       return bean;
   }
   /**
    * 获取beanClass可用的Advisor
    */
   Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   if (specificInterceptors != DO_NOT_PROXY) {
       this.advisedBeans.put(cacheKey, Boolean.TRUE);
       // 基于Advisor,创建代理对象
       Object proxy = createProxy(
               bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
       this.proxyTypes.put(cacheKey, proxy.getClass());
       return proxy;
   }
   // beanClass无可用的Advice,无需增强
   this.advisedBeans.put(cacheKey, Boolean.FALSE);
   return bean;
}

6. 构建Advisor

bean是否要增强,是通过beanClass是否有可用的Advisor来判断的。那么,Advisor是怎么来的呢?

查找bean可用的Advisor的方法在AbstractAdvisorAutoProxyCreator#findEligibleAdvisors(),先从容器内找出所有的Advisor,也就是我们在@Aspect类里定义的各种增强方法,然后根据切点表达式过滤出可以应用到当前beanClass的Advisor。然后将一个特殊的 * ExposeInvocationInterceptor插入到首位,最后将 * 排个序返回。

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
   /**
    * 查找容器内所有的Advisor:@Aspect类里定义的各种增强方法
    */
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   /**
    * 根据切点表达式,过滤出可以应用到beanClass的Advisor
    */
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   /**
    * 将ExposeInvocationInterceptor * 插入到第一个
    */
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
       eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

构建Advisor的职责交给了BeanFactoryAspectJAdvisorsBuilder类的buildAspectJAdvisors()方法,它首先从容器内找出所有加了@Aspect注解的bean,然后解析bean所有加了@Pointcut@Around@Before@After@AfterReturning@AfterThrowing注解的方法,将它们封装成Advisor对象。

/**
*将bean里面加了指定注解的方法封装成对应的Advice
*@Before -> AspectJMethodBeforeAdvice
* Around -> AspectJAroundAdvice
*@After -> AspectJAfterAdvice
*.......
*/
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);

容器内的Advisor对象并不能都应用到目标bean对象,所以Spring还会调用findAdvisorsThatCanApply()方法过滤出当前beanClass可用的Advisor。

7. 创建代理对象

如果当前bean有可用的Advisor,也就意味着需要对bean做增强,此时会调用createProxy()方法创建增强后的代理对象。

问题:使用JDK代理还是CGLIB代理?

我们可以通过属性proxyTargetClass强制使用CGLIB代理,如果不指定,Spring的规则是:如果beanClass实现了接口,且接口至少有一个自定义方法,那么就用JDK代理,否则用CGLIB代理。

protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
   // 获取beanClass实现的所有接口
   Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
   boolean hasReasonableProxyInterface = false;
   /**
    * 遍历接口
    * 1.非配置的回调接口,即Spring内置的接口不算,例如InitializingBean、Aware等接口
    * 2.非内部语言接口,例如GroovyObject
    * 3.接口至少有一个自定义方法
    */
   for (Class<?> ifc : targetInterfaces) {
       if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
               ifc.getMethods().length > 0) {
           hasReasonableProxyInterface = true;
           break;
       }
   }
   if (hasReasonableProxyInterface) {
       // Must allow for introductions; can't just set interfaces to the target's interfaces only.
       for (Class<?> ifc : targetInterfaces) {
           proxyFactory.addInterface(ifc);
       }
   } else {
       // 没有实现有效接口,使用CGLIB代理
       proxyFactory.setProxyTargetClass(true);
   }
}

最终,Spring会通过ProxyFactory去创建代理对象。

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 proxyFactory = new ProxyFactory();
   // 属性赋值给ProxyFactory
   proxyFactory.copyFrom(this);
   /**
    * 判断使用JDK代理还是CGLIB代理
    * 如果beanClass实现了接口,且接口至少有一个自定义方法,则使用JDK代理
    * 否则CGLIB代理
    */
   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);
   // 是否冻结,也就是Advisor不可再变更
   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
       proxyFactory.setPreFiltered(true);
   }
   // 创建 *  两种方式 JDK CGlib
   return proxyFactory.getProxy(getProxyClassLoader());
}

AopProxy有两种实现,分别是**JdkDynamicAopProxy****CglibAopProxy****,前者使用JDK * 的方式将Advice织入bean,后者通过CGLIB生成子类的方式将Advice织入bean。**我们以CGLIB为例,创建代理对象的方法是CglibAopProxy#getProxy()

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
   if (logger.isTraceEnabled()) {
       logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
   }
   try {
       Class<?> rootClass = this.advised.getTargetClass();
       Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

Class<?> proxySuperClass = rootClass;
       if (ClassUtils.isCglibProxyClass(rootClass)) {
           proxySuperClass = rootClass.getSuperclass();
           Class<?>[] additionalInterfaces = rootClass.getInterfaces();
           for (Class<?> additionalInterface : additionalInterfaces) {
               this.advised.addInterface(additionalInterface);
           }
       }
       // Validate the class, writing log messages as necessary.
       validateClassIfNecessary(proxySuperClass, 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);
       /**
        * 会实现接口
        * @see org.springframework.aop.SpringProxy
        * @see org.springframework.aop.framework.Advised
        */
       enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
       enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
       enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
       /**
        * 获取方法回调,AOP主要看
        * @see DynamicAdvisedInterceptor
        */
       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);
   } catch (CodeGenerationException | IllegalArgumentException ex) {
       throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
               ": Common causes of this problem include using a final class or a non-visible class",
               ex);
   } catch (Throwable ex) {
       // TargetSource.getTarget() failed
       throw new AopConfigException("Unexpected AOP exception", ex);
   }
}

Spring会通过Enhancer去创建子类对象来增强目标bean,生成的子类默认会实现org.springframework.aop.SpringProxy接口用来标记它是一个Spring生成的代理类。我们重点看给Enhancer对象设置的Callback,因为它会对方法做拦截,也就是说,我们调用子类的增强方法,其实就是在调用Callback#intercept()。Spring考虑的比较全面,会针对mainequalshashCode等方法做处理,针对AOP我们主要看AopInterceptor即可。

/**
* Spring考虑了很多情况,
*比如对main、equals、hashCode方法的拦截
*AOP主要看aopInterceptor
*/
Callback[] mainCallbacks = new Callback[]{
aopInterceptor,ll for normal advice
targetInterceptor,// invoke target without considering advice,if optimized
new SerializableNo0p(),l/ no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};

aopInterceptor是DynamicAdvisedInterceptor子类对象,用于处理AOP方法调用,也就是说,AOP增强逻辑就在DynamicAdvisedInterceptor#intercept()里。

// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

8. DynamicAdvisedInterceptor

调用CGLIB增强子类的方法,其实会触发DynamicAdvisedInterceptor#intercept()方法,看看Spring增强的逻辑。

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
   Object oldProxy = null;
   boolean setProxyContext = false;
   Object target = null;
   TargetSource targetSource = this.advised.getTargetSource();
   try {
       /**
        * 是否要暴露代理对象,以通过AopContext获取
        * 写入ThreadLocal
        */
       if (this.advised.exposeProxy) {
           oldProxy = AopContext.setCurrentProxy(proxy);
           setProxyContext = true;
       }
       /**
        * 获取目标Bean实例
        * 如果是prototype 此时会创建新的实例
        */
       target = targetSource.getTarget();
       Class<?> targetClass = (target != null ? target.getClass() : null);
       /**
        * 获取方法能应用到的Advice, * 调用链
        * @see org.springframework.aop.interceptor.ExposeInvocationInterceptor
        * @see org.springframework.aop.aspectj.AspectJAfterThrowingAdvice
        * @see org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor
        * @see org.springframework.aop.aspectj.AspectJAfterAdvice
        * @see org.springframework.aop.aspectj.AspectJAroundAdvice
        * @see org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor
        */
       List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
       Object retVal;
       if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
           /**
            * 没有Advice,直接调用父类方法
            */
           Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
           retVal = methodProxy.invoke(target, argsToUse);
       } else {
           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) {
           AopContext.setCurrentProxy(oldProxy);
       }
   }
}

方法 * 主要做了三件事:

  • 判断是否要暴露代理对象,如果要则写入ThreadLocal

  • 获取方法能应用到的Advice,构建 * 调用链

  • 触发 * 调用链

如果方法没有可用的Advice,也就不需要增强,直接调用父类方法即可。反之方法需要增强,Spring会new一个CglibMethodInvocation对象,触发 * 调用链。

9. CglibMethodInvocation

CglibMethodInvocation#proceed()方法会触发 * 调用链,Spring通过一个int变量currentInterceptorIndex来记录当前执行的 * 索引,通过和总的 * 数量判断是否调用完所有的 * ,如果是则通过invokeJoinpoint()方法去调用目标方法,反之则去执行Advice增强。

public Object proceed() throws Throwable {
   /**
    * currentInterceptorIndex 当前执行的 * 索引
    * interceptorsAndDynamicMethodMatchers.size() 所有拦击器个数
    * 执行完最后一个 * ,就要执行目标方法了
    */
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
       // 最终反射调用目标方法
       return invokeJoinpoint();
   }
// 触发Advice增强
   Object interceptorOrInterceptionAdvice =
           this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
   if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
       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 {
           return proceed();
       }
   } else {
       return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

10. Advice子类

Spring AOP提供了五种Advice增强,分别是通过@Around@Before@After@AfterReturning@AfterThrowing注解标记的方法。这五种Advice分别对应五个Advice子类实现。

1、AspectJAfterThrowingAdvice

先走下一个 * ,只有在发生异常时,才触发的Advice。

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   try {
       // 先走下一个 *
       return mi.proceed();
   } catch (Throwable ex) {
       if (shouldInvokeOnThrowing(ex)) {
           /**
            * 只有发生异常了,才会执行@AfterThrowing Advice
            */
           invokeAdviceMethod(getJoinPointMatch(), null, ex);
       }
       throw ex;
   }
}

2、AfterReturningAdviceInterceptor

走剩下所有的 * ,拿到返回结果。正常执行完毕才触发的Advice,如果发生异常则不触发。

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   // 直接走剩下的 * ,拿到返回结果
   Object retVal = mi.proceed();
   /**
    * 正常执行完毕,才触发 @AfterReturning Advice
    * 如果期间发生异常,则不触发
    */
   this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
   return retVal;
}

3、AspectJAfterAdvice

先走下一个 * ,执行完毕再最终调用的Advice,不论是否发生异常。

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   try {
       /**
        * 先走下一个 * ,执行完毕再最终调用@After Advice
        */
       return mi.proceed();
   } finally {
       /**
        * 执行@After Advice方法
        * @After Advice一定会被调用,不管是否发生异常,因为在finally
        */
       invokeAdviceMethod(getJoinPointMatch(), null, null);
   }
}

4、AspectJAroundAdvice

直接触发Advice,是否继续调用后续Advice由我们自己决定。

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   if (!(mi instanceof ProxyMethodInvocation)) {
       throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
   }
   /**
    * 直接触发Advice,是否继续调用后续Advice,由@Around Advice自己决定
    */
   ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
   ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
   JoinPointMatch jpm = getJoinPointMatch(pmi);
   return invokeAdviceMethod(pjp, jpm, null, null);
}

5、MethodBeforeAdviceInterceptor

先触发当前Advice,再调用下一个Advice。

@Override
public Object invoke(MethodInvocation mi) throws Throwable {
   /**
    * 先触发 @Before Advice
    * 再调用下一个Advice
    */
   this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
   return mi.proceed();
}

来源:https://javap.blog.csdn.net/article/details/128499978

标签:Spring,AOP,源码
0
投稿

猜你喜欢

  • Kotlin协程之Flow基础原理示例解析

    2021-10-17 21:07:44
  • MyBatis查询数据返回null的解决

    2021-11-17 20:46:48
  • Spring Boot小型项目如何使用异步任务管理器实现不同业务间的解耦

    2022-11-21 07:49:54
  • C语言单向链表的表示与实现实例详解

    2022-01-24 21:38:33
  • 解析Java的JNI编程中的对象引用与内存泄漏问题

    2023-03-19 20:59:28
  • Unity 数据存储和读取的方法汇总

    2021-12-12 11:39:47
  • Springboot内置tomcat配置虚拟路径过程解析

    2021-12-21 06:06:03
  • Android使用ViewPager实现类似laucher左右拖动效果

    2022-05-18 20:33:59
  • 详解Spring Cloud Eureka多网卡配置总结

    2023-11-09 07:33:15
  • Java web的读取Excel简单实例代码

    2023-05-29 08:25:37
  • Android音乐播放器制作 加入控制台(三)

    2022-04-15 05:09:30
  • Android开发自学笔记(六):声明权限和Activity

    2021-05-26 07:25:49
  • 详解Mybatis的缓存

    2022-10-23 22:49:13
  • java单向链表的实现实例

    2023-10-23 20:36:10
  • 深入剖析java中的集合框架

    2022-04-27 18:48:16
  • Java Object定义三个点实现代码

    2023-11-21 06:05:07
  • 详解Java中final的用法

    2022-09-22 10:20:32
  • 基于C#实现端口扫描器(单线程和多线程)

    2021-10-16 20:32:23
  • Android实现在xml文件中引用自定义View的方法分析

    2021-05-28 01:43:57
  • 使用Java实现三种等级的扫雷游戏(完整版)

    2023-05-10 07:34:17
  • asp之家 软件编程 m.aspxhome.com