SpringBoot-AOP源码梳理

1. @EnableAspectJAutoProxy 注解做了什么?

在springboot中,@EnableAspectJAutoProxy 注解开启AOP , 在这个注解里面,通过@Import 给容器中导入AspectJAutoProxyRegistrar 对象.

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
    
    ...}

AspectJAutoProxyRegistrar 实现了ImportBeanDefinitionRegistrar接口,通过这个接口可以向容器中增加Bean的定义。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
    
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
    
	
		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.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); 这一句往里走,最后创建了一个AnnotationAwareAspectJAutoProxyCreator 对象的Bean定义,加到注册器中,key为org.springframework.aop.config.internalAutoProxyCreator.

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, 	@Nullable Object source) {
    
    
  return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    
    
  Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
  if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
    
    
    ...
  } else {
    
    
    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", -2147483648);
    beanDefinition.setRole(2);
    registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
    return beanDefinition;
  }
}

2. 什么时候注册1中的AnnotationAwareAspectJAutoProxyCreator对象的定义?

在AspectJAutoProxyRegistrar.registerBeanDefinitions() 方法打断点调试,查看调用链路
在这里插入图片描述
大致流程是

spring容器启动阶段的 AbstractApplicationContext.refresh()

invokeBeanFactoryPostProcessors(beanFactory) // 调用工厂的后置处理器, 增加即将加入容器中Bean的定义

this**.**reader.loadBeanDefinitions(configClasses); // 加载所有配置类, 有@Configration注解的类

loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); // 把配置类中import引入的注册器类加载进来

AspectJAutoProxyRegistrar.registerBeanDefinitions() // 进入到aop的注册bean定义的方法。

3. 什么时候创建1中的AnnotationAwareAspectJAutoProxyCreator对象?

在这里插入图片描述
通过AnnotationAwareAspectJAutoProxyCreator 类的继承关系,可以看到它实现了BeanPostProcessor. 在spring容器的启动过程中 AbstractApplicationContext.refresh() 有专门负责加载所有实现BeanPostProcessor接口的方法

registerBeanPostProcessors(beanFactory); // 加载所有实现BeanPostProcessor接口的方法
它里面的内容包括如下:

// 获取所有实现了BeanPostProcessor接口的bean的名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); 
...
  // 逐个创建Bean
  for (String ppName : postProcessorNames) {
    
    
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    
    
      // BeanFatory.getBean方法获取到的就是已经创建好的Bean了
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
      priorityOrderedPostProcessors.add(pp);
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
    
    
        internalPostProcessors.add(pp);
      }
    }
    else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
    
    
      orderedPostProcessorNames.add(ppName);
    }
    else {
    
    
      nonOrderedPostProcessorNames.add(ppName);
    }
  }
...
  // 把创建好的bean加到容器中
  registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

4. 加到容器中的AnnotationAwareAspectJAutoProxyCreator 怎么生效呢?

AOP的本质是代理,那么就会有创建Bean的时候,不会使用原本类型指定的对象,而是创建一个增强的对象。那么我们就从创建bean的过程中寻找。我们知道spring 容器启动的过程中,会先加载 BeanPostProcessor 等类型的bean,像我们代码中自己定义的切面等其他业务相关bean,都是之后加载的,从spring容器启动过程的refresh()方法的代码顺序也可以看出来,这一点在这里也不重要,我只是提一下。

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
...
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

既然创建的对象是代理对象,那么直接在AbstractAutowireCapableBeanFactory 类的createBean 方法里面打断点,并且给断电加上Condition, 只在创建我们定义的需要被切的对象的时候断住,比如我写了一个Say这个类,那么我加的条件就是beanName.equals(“say”). 一步步的调试,发现走到applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName) -> wrapIfNecessary(bean, beanName, cacheKey) 方法中的时候,有这么一段代码

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

这个方法是在 AbstractAutoProxyCreator 的 注释也说的很清楚了,如果有通知就创建代理。通过切点表达式和类的关系,就能找到我们定义的通知方法,被封装为Advisor对象。代理创建完成后,可以看到通知方法作为拦截器链添加到了道理对象中。其中的拦截器链已经根据Before, After等注解信息排好了顺序,排序是使用 ReflectiveAspectJAdvisorFactory 类的METHOD_COMPARATOR 方法实现了,里面已经定义好了各个注解的顺序。
在这里插入图片描述
至此,需要增强的对象创建完成,调用的时候,进入CglibAopProxy 的 intercept 方法,因为我这里是对类进行的增强,所以spring自动的选则了使用cglib 代理。

先获取所有的增强方法组成的拦截器链

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

把代理对象(Cglib增强后的对象),目标对象(Say),方法,参数,连接器链等信息封装为一个CglibMethodInvocation 对象,并执行该对象的.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);
  }
}

调试可以看到链式的调用,逐个拦截器不断的调用 mi.proceed(); 逐渐深入到最后一个拦截器MethodBeforeAdviceInterceptor 的时候,可以看到执行了前置通知的方法

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

前置通知执行完以后,mo.proceed()方法中满足了执行方法本体的条件,被增强的方法本体执行。

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

执行完后线程栈退回到上一层的拦截器,是AspectJAfterAdvice, 因为是在finally 块中的,所以必然执行。

public Object invoke(MethodInvocation mi) throws Throwable {
    
    
   try {
    
    
      return mi.proceed();
   }
   finally {
    
    
      invokeAdviceMethod(getJoinPointMatch(), null, null);
   }
}

结束后线程退回到AfterReturningAdviceInterceptor 拦截器,到这里为止所有的拦截器中都没有捕获异常,所以如果前面有异常的时候,后置拦截器的内容就不执行了。

public Object invoke(MethodInvocation mi) throws Throwable {
    
    
   Object retVal = mi.proceed();
   this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
   return retVal;
}

之后回到AspectJAfterThrowingAdvice 拦截器,这里是在catch 块中,没有异常就不执行。

public Object invoke(MethodInvocation mi) throws Throwable {
    
    
   try {
    
    
      return mi.proceed();
   }
   catch (Throwable ex) {
    
    
      if (shouldInvokeOnThrowing(ex)) {
    
    
         invokeAdviceMethod(getJoinPointMatch(), null, ex);
      }
      throw ex;
   }
}

5. 看的时候一定要写个demo,一遍调试一遍看,光读文字看不懂的。我的demo如下

/**
 * Author:   susq
 * Date:     2019-08-04 12:06
 */
public class Say {
    
    

    public void sayHello() {
    
    
        log.info("Say -- sayHello : hello !");
    }
}
@Aspect
public class SayAspect {
    
    

    @Pointcut("execution(public * com.su.demo.aop.Say.sayHello(..))")
    public void sayPointCut() {
    
    }

    @After("sayPointCut()")
    public void afterSay() {
    
    
        System.out.println("=====afterSay=====");
    }

    @AfterThrowing("sayPointCut()")
    public void afterThrow() {
    
    
        System.out.println("=====afterThrow=====");
    }

    @Before("sayPointCut()")
    public void beforeSay() {
    
    
        System.out.println("=====beforeSay=====");
    }

    @AfterReturning("sayPointCut()")
    public void afterReturn() {
    
    
        System.out.println("=====afterReturn=====");
    }

}
@EnableAspectJAutoProxy
@Configuration
public class SayConfig {
    
    

    @Bean
    public Say say() {
    
    
        return new Say();
    }

    @Bean
    public SayAspect sayAspect() {
    
    
        return new SayAspect();
    }
}
public class AppTest {
    
    

    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(SayConfig.class);
        Say say = configApplicationContext.getBean(Say.class);
        say.sayHello();
    }
}

猜你喜欢

转载自blog.csdn.net/u013041642/article/details/98473721
今日推荐