文章结构

  1. 首先提到了SpringAOP是基于postProcessBeforeInstantiationpostProcessAfterInstantiation两个方法实现的,这篇文章主讲postProcessBeforeInstantiation
  2. 加载Advisor
  3. 获取所有的Advisor又对Advisor进行了一系列的封装

    Advisor类

    看代码前首先了解一个类Advisor,如果从代码执行角度来看,Spring AOP的执行过程分为四大步骤:
  • 步骤一:Spring框架生成Advisor实例,可以是@Aspect@Async等注解生成的实例,也可以是程序员自定义的AbstractAdvisor子类的实例。
  • 步骤二:Spring框架在目标实例初始化完成后,也就是使用BeanPostProcessorpostProcessAfterInitialization方法,根据Advisor实例中切入点Pointcut的定义,选择出适合该目标对象的Advisor实例。
  • 步骤三:Spring框架根据Advisor实例生成代理对象。
  • 步骤四:调用方法执行过程时,Spring框架执行Advisor实例的通知Advice逻辑。

  Spring中有大量的机制都是通过AOP实现的,比如说@Async的异步调用和@Transational。此外,用户也可以使用@Aspect注解定义切面或者直接继承AbstractPointcutAdvisor来提供切面逻辑。上述这些情况下,AOP都会生成对应的Advisor实例

Spring AOP中这个Advisor类,看看它的继承关系
image.png

在上篇文章中我们搭建了一个阅读源码的demo工程,然后简单介绍了一下@EnableAspectJAutoProxy注解,这个注解最重要的功能就是为向Spring中注入了一个bean, AnnotationAwareAspectJAutoProxyCreator ,本篇文章就继续来撸AOP的源码

前文已经简单提到了这个类的功能,不过这里还是要先看一下这个类的继承图
image.png

观察类图可知,AnnotationAwareAspectJAutoProxyCreator 这个类间接实现了BeanPostProcessor接口。还记得我们之前在对SpringIOC的源码进行解析时提到过,Spring在实例化Bean的前后会分别调用方法postProcessBeforeInstantiationpostProcessAfterInstantiation
而AOP的整体逻辑就是通过这两个方法来实现的

resolveBeforeInstantiation()

在前面SpringIOC中我们跟踪过IOC容器初始化的过程,其中AbstractAutowireCapableBeanFactor 方法createBean()里, resolveBeforeInstantiation()方法会对 BeanPostProcessors 处理,调用 postProcessBeforeInstantiationpostProcessAfterInstantiation 生成Bean的代理对象

  1. @Override
  2. protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
  3. throws BeanCreationException {
  4. if (logger.isDebugEnabled()) {
  5. logger.debug("Creating instance of bean '" + beanName + "'");
  6. }
  7. RootBeanDefinition mbdToUse = mbd;
  8. // Make sure bean class is actually resolved at this point, and
  9. // clone the bean definition in case of a dynamically resolved Class
  10. // which cannot be stored in the shared merged bean definition.
  11. Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
  12. if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
  13. mbdToUse = new RootBeanDefinition(mbd);
  14. mbdToUse.setBeanClass(resolvedClass);
  15. }
  16. // Prepare method overrides.
  17. try {
  18. mbdToUse.prepareMethodOverrides();
  19. }
  20. catch (BeanDefinitionValidationException ex) {
  21. throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
  22. beanName, "Validation of method overrides failed", ex);
  23. }
  24. try {
  25. //代理的BeanPostProcessors处理,调用postProcessBeforeInstantiation 和 postProcessAfterInstantiation
  26. // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
  27. Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
  28. if (bean != null) {
  29. return bean;
  30. }
  31. }
  32. catch (Throwable ex) {
  33. throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
  34. "BeanPostProcessor before instantiation of bean failed", ex);
  35. }
  36. try {
  37. Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  38. if (logger.isDebugEnabled()) {
  39. logger.debug("Finished creating instance of bean '" + beanName + "'");
  40. }
  41. return beanInstance;
  42. }
  43. catch (BeanCreationException ex) {
  44. // A previously detected exception with proper bean creation context already...
  45. throw ex;
  46. }
  47. catch (ImplicitlyAppearedSingletonException ex) {
  48. // An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
  49. throw ex;
  50. }
  51. catch (Throwable ex) {
  52. throw new BeanCreationException(
  53. mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
  54. }
  55. }
  56. @Nullable
  57. protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
  58. Object bean = null;
  59. if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
  60. // Make sure bean class is actually resolved at this point.
  61. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
  62. Class<?> targetType = determineTargetType(beanName, mbd);
  63. if (targetType != null) {
  64. bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
  65. if (bean != null) {
  66. bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
  67. }
  68. }
  69. }
  70. mbd.beforeInstantiationResolved = (bean != null);
  71. }
  72. return bean;
  73. }
  74. @Nullable
  75. protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
  76. for (BeanPostProcessor bp : getBeanPostProcessors()) {
  77. if (bp instanceof InstantiationAwareBeanPostProcessor) {
  78. InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
  79. //这里进行调用
  80. Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
  81. if (result != null) {
  82. return result;
  83. }
  84. }
  85. }
  86. return null;
  87. }
  88. @Override
  89. public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
  90. throws BeansException {
  91. Object result = existingBean;
  92. for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
  93. Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
  94. if (current == null) {
  95. return result;
  96. }
  97. result = current;
  98. }
  99. return result;
  100. }

postProcessBeforeInstantiation

首先看一下这个postProcessBeforeInstantiation方法,它是在bean实例化之前调用的,主要是针对切面类。这个方法不在AnnotationAwareAspectJAutoProxyCreator 这个类中,而是在其父类AbstractAutoProxyCreator

  1. public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
  2. Object cacheKey = getCacheKey(beanClass, beanName);
  3. if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
  4. if (this.advisedBeans.containsKey(cacheKey)) {
  5. return null;
  6. }
  7. //不是功能实现的基础类,shouldSkip()方法判断是否跳过, 不跳过则加载bean上的Advisor列表
  8. if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
  9. this.advisedBeans.put(cacheKey, Boolean.FALSE);
  10. return null;
  11. }
  12. }
  13. TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
  14. if (targetSource != null) {
  15. if (StringUtils.hasLength(beanName)) {
  16. this.targetSourcedBeans.add(beanName);
  17. }
  18. Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
  19. Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
  20. this.proxyTypes.put(cacheKey, proxy.getClass());
  21. return proxy;
  22. }
  23. return null;
  24. }

加载Advisors列表

上方代码中最重要的一个方法就是shouldSkip方法了,这个方法被AspectJAwareAdvisorAutoProxyCreator所重载

  1. protected boolean shouldSkip(Class<?> beanClass, String beanName) {
  2. //查找所有标识了@Aspect注解的类,这里是重点,接着往下看
  3. List<Advisor> candidateAdvisors = findCandidateAdvisors();
  4. for (Advisor advisor : candidateAdvisors) {
  5. if (advisor instanceof AspectJPointcutAdvisor) {
  6. if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
  7. return true;
  8. }
  9. }
  10. }
  11. return super.shouldSkip(beanClass, beanName);
  12. }
  13. protected List<Advisor> findCandidateAdvisors() {
  14. return this.advisorRetrievalHelper.findAdvisorBeans();
  15. }
  16. protected List<Advisor> findCandidateAdvisors() {
  17. List<Advisor> advisors = super.findCandidateAdvisors();
  18. //buildAspectJAdvisors是重点
  19. advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
  20. return advisors;
  21. }

一个长方法buildAspectJAdvisors

  1. public List<Advisor> buildAspectJAdvisors() {
  2. //所有包含Aspect注解类的名称集合
  3. List<String> aspectNames = this.aspectBeanNames;
  4. if (aspectNames == null) {
  5. synchronized (this) {
  6. aspectNames = this.aspectBeanNames;
  7. //这个双重检查是不是在学习安全的单例模式的时候见过
  8. if (aspectNames == null) {
  9. List<Advisor> advisors = new LinkedList<Advisor>();
  10. aspectNames = new LinkedList<String>();
  11. //获取所有Bean名称
  12. String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
  13. this.beanFactory, Object.class, true, false);
  14. for (String beanName : beanNames) {
  15. //判断是否符合条件,比如说有时会排除一些类,不让这些类注入进Spring
  16. if (!isEligibleBean(beanName)) {
  17. continue;
  18. }
  19. Class<?> beanType = this.beanFactory.getType(beanName);
  20. if (beanType == null) {
  21. continue;
  22. }
  23. //判断Bean的Class上是否标识@Aspect注解
  24. if (this.advisorFactory.isAspect(beanType)) {
  25. aspectNames.add(beanName);
  26. AspectMetadata amd = new AspectMetadata(beanType, beanName);
  27. if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
  28. MetadataAwareAspectInstanceFactory factory =
  29. new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
  30. //下一步说,重点的重点,getAdvisors会解析这个类中的@Pointcut、@Before等注解方法封装为Advisor列表,见下
  31. List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
  32. if (this.beanFactory.isSingleton(beanName)) {
  33. //将解析的Bean名称及类上的Advisors缓存起来,每个Bean只解析一次
  34. this.advisorsCache.put(beanName, classAdvisors);
  35. }
  36. else {
  37. this.aspectFactoryCache.put(beanName, factory);
  38. }
  39. advisors.addAll(classAdvisors);
  40. }
  41. else {
  42. if (this.beanFactory.isSingleton(beanName)) {
  43. throw new IllegalArgumentException("Bean with name '" + beanName +
  44. "' is a singleton, but aspect instantiation model is not singleton");
  45. }
  46. MetadataAwareAspectInstanceFactory factory =
  47. new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
  48. this.aspectFactoryCache.put(beanName, factory);
  49. advisors.addAll(this.advisorFactory.getAdvisors(factory));
  50. }
  51. }
  52. }
  53. this.aspectBeanNames = aspectNames;
  54. return advisors;
  55. }
  56. }
  57. }
  58. if (aspectNames.isEmpty()) {
  59. return Collections.emptyList();
  60. }
  61. List<Advisor> advisors = new LinkedList<Advisor>();
  62. for (String aspectName : aspectNames) {
  63. //从缓存中获取当前Bean的切面实例,如果不为空,则指明当前Bean的Class标识了@Aspect,且有切面方法
  64. List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
  65. if (cachedAdvisors != null) {
  66. advisors.addAll(cachedAdvisors);
  67. }
  68. else {
  69. MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
  70. advisors.addAll(this.advisorFactory.getAdvisors(factory));
  71. }
  72. }
  73. return advisors;
  74. }

advisorFactory.getAdvisors

advisorFactory.getAdvisors()方法会从@Aspect标识的类上获取@Before@Pointcut等注解的信息及其标识的方法的信息,生成Advisor

  1. public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
  2. Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
  3. String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
  4. //校验类的合法性相关
  5. validate(aspectClass);
  6. MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
  7. new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
  8. List<Advisor> advisors = new LinkedList<Advisor>();
  9. //获取这个类所有的Advisor方法
  10. for (Method method : getAdvisorMethods(aspectClass)) {
  11. //生成Advisor实例,见下
  12. Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
  13. if (advisor != null) {
  14. advisors.add(advisor);
  15. }
  16. }
  17. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
  18. Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
  19. advisors.add(0, instantiationAdvisor);
  20. }
  21. for (Field field : aspectClass.getDeclaredFields()) {
  22. Advisor advisor = getDeclareParentsAdvisor(field);
  23. if (advisor != null) {
  24. advisors.add(advisor);
  25. }
  26. }
  27. return advisors;
  28. }
  29. //获取类的的方法
  30. private List<Method> getAdvisorMethods(Class<?> aspectClass) {
  31. final List<Method> methods = new LinkedList<Method>();
  32. ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
  33. @Override
  34. public void doWith(Method method) throws IllegalArgumentException {
  35. //在@Aspect标识的类内部排除@Pointcut标识之外的所有方法,得到的方法集合包括继承自父类的方法,包括继承自Object的方法
  36. if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
  37. methods.add(method);
  38. }
  39. }
  40. });
  41. //对得到的所有方法排序,
  42. //如果方法标识了切面注解,则按@Around, @Before, @After, @AfterReturning, @AfterThrowing的顺序排序
  43. //如果没有标识这些注解,则按方法名称的字符串排序,
  44. //有注解的方法排在无注解的方法之前
  45. //最后的排序应该是这样的Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class。。。
  46. Collections.sort(methods, METHOD_COMPARATOR);
  47. return methods;
  48. }
  49. public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
  50. int declarationOrderInAspect, String aspectName) {
  51. //再次校验类的合法性
  52. validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
  53. //切点表达式的包装类里面包含这些东西:execution(public * cn.shiyujun.service.IOCService.hollo(..))
  54. //或者@Around中的value值,都会被封装到AspectJExpressionPointcut中
  55. AspectJExpressionPointcut expressionPointcut = getPointcut(
  56. candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
  57. if (expressionPointcut == null) {
  58. return null;
  59. }
  60. //根据方法、切点、AOP实例工厂、类名、序号生成Advisor实例,详细代码往下看
  61. return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
  62. this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
  63. }
  64. private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
  65. //查询方法上的切面注解,根据注解生成相应类型的AspectJAnnotation,在调用AspectJAnnotation的构造函数的同时
  66. //根据注解value或pointcut属性得到切点表达式,有argNames则设置参数名称
  67. AspectJAnnotation<?> aspectJAnnotation =
  68. AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
  69. //过滤那些不含@Before, @Around, @After, @AfterReturning, @AfterThrowing注解的方法
  70. if (aspectJAnnotation == null) {
  71. return null;
  72. }
  73. //生成带表达式的切面切入点,设置其切入点表达式
  74. AspectJExpressionPointcut ajexp =
  75. new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
  76. ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
  77. ajexp.setBeanFactory(this.beanFactory);
  78. return ajexp;
  79. }

InstantiationModelAwarePointcutAdvisorImpl 构造方法

  1. public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
  2. Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
  3. MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
  4. this.declaredPointcut = declaredPointcut;
  5. this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
  6. this.methodName = aspectJAdviceMethod.getName();
  7. this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
  8. this.aspectJAdviceMethod = aspectJAdviceMethod;
  9. this.aspectJAdvisorFactory = aspectJAdvisorFactory;
  10. this.aspectInstanceFactory = aspectInstanceFactory;
  11. this.declarationOrder = declarationOrder;
  12. this.aspectName = aspectName;
  13. if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
  14. Pointcut preInstantiationPointcut = Pointcuts.union(
  15. aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
  16. this.pointcut = new PerTargetInstantiationModelPointcut(
  17. this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
  18. this.lazy = true;
  19. }
  20. else {
  21. this.pointcut = this.declaredPointcut;
  22. this.lazy = false;
  23. //重点在这里
  24. this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
  25. }
  26. }
  27. private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
  28. //再往下看
  29. Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
  30. this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
  31. return (advice != null ? advice : EMPTY_ADVICE);
  32. }

reflectiveAspectJAdvisorFactory.getAdvice

  1. //调用这里的getAdvice
  2. public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
  3. public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
  4. MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
  5. Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
  6. //又是一次校验
  7. validate(candidateAspectClass);
  8. AspectJAnnotation<?> aspectJAnnotation =
  9. AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
  10. if (aspectJAnnotation == null) {
  11. return null;
  12. }
  13. if (!isAspect(candidateAspectClass)) {
  14. throw new AopConfigException("Advice must be declared inside an aspect type: " +
  15. "Offending method '" + candidateAdviceMethod + "' in class [" +
  16. candidateAspectClass.getName() + "]");
  17. }
  18. if (logger.isDebugEnabled()) {
  19. logger.debug("Found AspectJ method: " + candidateAdviceMethod);
  20. }
  21. AbstractAspectJAdvice springAdvice;
  22. //根据注解类型生成不同的通知实例
  23. switch (aspectJAnnotation.getAnnotationType()) {
  24. case AtBefore:
  25. springAdvice = new AspectJMethodBeforeAdvice(
  26. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  27. break;
  28. case AtAfter:
  29. springAdvice = new AspectJAfterAdvice(
  30. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  31. break;
  32. case AtAfterReturning:
  33. springAdvice = new AspectJAfterReturningAdvice(
  34. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  35. AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
  36. if (StringUtils.hasText(afterReturningAnnotation.returning())) {
  37. springAdvice.setReturningName(afterReturningAnnotation.returning());
  38. }
  39. break;
  40. case AtAfterThrowing:
  41. springAdvice = new AspectJAfterThrowingAdvice(
  42. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  43. AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
  44. if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
  45. springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
  46. }
  47. break;
  48. case AtAround:
  49. springAdvice = new AspectJAroundAdvice(
  50. candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
  51. break;
  52. case AtPointcut:
  53. if (logger.isDebugEnabled()) {
  54. logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
  55. }
  56. return null;
  57. default:
  58. throw new UnsupportedOperationException(
  59. "Unsupported advice type on method: " + candidateAdviceMethod);
  60. }
  61. //设置通知方法所属的类
  62. springAdvice.setAspectName(aspectName);
  63. //设置通知的序号,同一个类中有多个切面注解标识的方法时,按上方说的排序规则来排序,
  64. //其序号就是此方法在列表中的序号,第一个就是0
  65. springAdvice.setDeclarationOrder(declarationOrder);
  66. //获取通知方法的所有参数
  67. String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
  68. //将通知方法上的参数设置到通知中
  69. if (argNames != null) {
  70. springAdvice.setArgumentNamesFromStringArray(argNames);
  71. }
  72. //计算参数绑定工作,此方法详解请接着往下看
  73. springAdvice.calculateArgumentBindings();
  74. return springAdvice;
  75. }
  76. }

校验方法参数并绑定(argNames()和arg())

  1. public synchronized final void calculateArgumentBindings() {
  2. if (this.argumentsIntrospected || this.parameterTypes.length == 0) {
  3. return;
  4. }
  5. int numUnboundArgs = this.parameterTypes.length;
  6. Class<?>[] parameterTypes = this.aspectJAdviceMethod.getParameterTypes();
  7. //切面注解标识的方法第一个参数要求是JoinPoint,或StaticPart,若是@Around注解则也可以是ProceedingJoinPoint
  8. if (maybeBindJoinPoint(parameterTypes[0]) || maybeBindProceedingJoinPoint(parameterTypes[0])) {
  9. numUnboundArgs--;
  10. }
  11. else if (maybeBindJoinPointStaticPart(parameterTypes[0])) {
  12. numUnboundArgs--;
  13. }
  14. if (numUnboundArgs > 0) {
  15. //绑定属性
  16. bindArgumentsByName(numUnboundArgs);
  17. }
  18. this.argumentsIntrospected = true;
  19. }
  20. private void bindArgumentsByName(int numArgumentsExpectingToBind) {
  21. if (this.argumentNames == null) { //获取方法参数的名称
  22. this.argumentNames = createParameterNameDiscoverer().getParameterNames(this.aspectJAdviceMethod);
  23. }
  24. if (this.argumentNames != null) {
  25. // 往下看
  26. bindExplicitArguments(numArgumentsExpectingToBind);
  27. }
  28. else {
  29. throw new IllegalStateException("Advice method [" + this.aspectJAdviceMethod.getName() + "] " +
  30. "requires " + numArgumentsExpectingToBind + " arguments to be bound by name, but " +
  31. "the argument names were not specified and could not be discovered.");
  32. }
  33. }
  34. private void bindExplicitArguments(int numArgumentsLeftToBind) {
  35. //此属性用来存储方法未绑定的参数名称,及参数的序号
  36. this.argumentBindings = new HashMap<String, Integer>();
  37. int numExpectedArgumentNames = this.aspectJAdviceMethod.getParameterTypes().length;
  38. if (this.argumentNames.length != numExpectedArgumentNames) {
  39. throw new IllegalStateException("Expecting to find " + numExpectedArgumentNames +
  40. " arguments to bind by name in advice, but actually found " +
  41. this.argumentNames.length + " arguments.");
  42. }
  43. // So we match in number...,argumentIndexOffset代表第一个未绑定参数的顺序
  44. int argumentIndexOffset = this.parameterTypes.length - numArgumentsLeftToBind;
  45. for (int i = argumentIndexOffset; i < this.argumentNames.length; i++) {
  46. //存储未绑定的参数名称及其顺序的映射关系
  47. this.argumentBindings.put(this.argumentNames[i], i);
  48. }
  49. // Check that returning and throwing were in the argument names list if
  50. // specified, and find the discovered argument types.
  51. //如果是@AfterReturning注解的returningName 有值,验证,解析,同时得到定义返回值的类型
  52. if (this.returningName != null) {
  53. if (!this.argumentBindings.containsKey(this.returningName)) {
  54. throw new IllegalStateException("Returning argument name '" + this.returningName +
  55. "' was not bound in advice arguments");
  56. }
  57. else {
  58. Integer index = this.argumentBindings.get(this.returningName);
  59. this.discoveredReturningType = this.aspectJAdviceMethod.getParameterTypes()[index];
  60. this.discoveredReturningGenericType = this.aspectJAdviceMethod.getGenericParameterTypes()[index];
  61. }
  62. }
  63. //如果是@AfterThrowing注解的throwingName 有值,验证,解析,同时得到抛出异常的类型
  64. if (this.throwingName != null) {
  65. if (!this.argumentBindings.containsKey(this.throwingName)) {
  66. throw new IllegalStateException("Throwing argument name '" + this.throwingName +
  67. "' was not bound in advice arguments");
  68. }
  69. else {
  70. Integer index = this.argumentBindings.get(this.throwingName);
  71. this.discoveredThrowingType = this.aspectJAdviceMethod.getParameterTypes()[index];
  72. }
  73. }
  74. // configure the pointcut expression accordingly.
  75. configurePointcutParameters(argumentIndexOffset);
  76. }
  77. private void configurePointcutParameters(int argumentIndexOffset) {
  78. int numParametersToRemove = argumentIndexOffset;
  79. if (this.returningName != null) {
  80. numParametersToRemove++;
  81. }
  82. if (this.throwingName != null) {
  83. numParametersToRemove++;
  84. }
  85. String[] pointcutParameterNames = new String[this.argumentNames.length - numParametersToRemove];
  86. Class<?>[] pointcutParameterTypes = new Class<?>[pointcutParameterNames.length];
  87. Class<?>[] methodParameterTypes = this.aspectJAdviceMethod.getParameterTypes();
  88. int index = 0;
  89. for (int i = 0; i < this.argumentNames.length; i++) {
  90. if (i < argumentIndexOffset) {
  91. continue;
  92. }
  93. if (this.argumentNames[i].equals(this.returningName) ||
  94. this.argumentNames[i].equals(this.throwingName)) {
  95. continue;
  96. }
  97. pointcutParameterNames[index] = this.argumentNames[i];
  98. pointcutParameterTypes[index] = methodParameterTypes[i];
  99. index++;
  100. }
  101. //剩余的未绑定的参数会赋值给AspectJExpressionPointcut(表达式形式的切入点)的属性,以备后续使用
  102. this.pointcut.setParameterNames(pointcutParameterNames);
  103. this.pointcut.setParameterTypes(pointcutParameterTypes);
  104. }