【Spring源码】37. AOP准备工作之parse()详解(下篇)
上一篇文章我们详细介绍了parse()方法中的第一个步骤:注册自动代理模式创建器(【Spring源码】36. AOP准备工作之parse()详解(上篇)),这篇文章我们继续介绍parse()方法中的第二个步骤:解析子节点
解析<aop:config>下的子节点
继续解析<aop:config>子节点下的
-
<aop:pointcut> -
<aop:advice> -
<aop:aspect>

在这里会根据获取到的localName进入不同的if条件语句,进而执行不同的解析方法
-
parsePointcut()
-
parseAdvisor()
-
parseAspect()
下面我们按照我们的测试代码中的XML配置(如下图)捋一遍流程(。・ω・。)ノ

由于获取到的localName为"aspect",满足ASPECT.equals(localName)为true的条件,所以进入parseAspect()方法中

parseAspect()

先获取<aop:aspect>的两个属性:
id属性
ref属性(代表切面,必须配置)

接着解析<aop:aspect>下的declare-parents节点,通过DeclareParentsAdvisor作为beanClass加载,然后继续解析其他节点

在获取到节点后,遍历循环,解析其下的Advice类型的节点,通过调用isAdviceNode()判断遍历到的当前节点是否为Advice类型的节点
isAdviceNode()
判断是否为Advice节点

如上图中方法上面的注释,Advice类型的节点有5个:
-
{ @code before}
-
{ @code after}
-
{ @code after-returning}
-
{ @code after-throwing}
-
{ @code around}
与上面任何一个类型形同返回值即为true
解析成功则继续向下执行

parseAdvisor()

方法parseAdvisor()先生成了methodDefinition(解析advice中的"method"属性,并包装为MethodLocatingFactoryBean对象 )、aspectFactoryDef(关联aspectName,包装为SimpleBeanFactoryAwareAspectInstanceFactory对象)这两个RootBeanDefinition对象,并依次为他俩赋值

随后解析pointcut属性,将上面👆两个对象传入了方法createAdviceDefinition()中,包装为AspectJMethodBeforeAdvice对象返回并赋值给名为adviceDef的AbstractBeanDefinition对象

最后将这个对象包装为名为advisorDefinition的RootBeanDefinition对象并为相关的属性赋值

最后完成注册,就可以在parseContext对象的readerContext -> reader -> registry -> beanDefinitionMap属性中看到这个AspectJPointcutAdvisor对象叻(AspectJPointcutAdvisor#0)

那么问题来了:这些生成的RootBeanDefinition对象有什么区别吗,他们具体都是哪些类呢?
我们先来详细介绍下createAdviceDefinition()这个方法
createAdviceDefinition()
进入方法createAdviceDefinition()

首先根据adviceElement节点通过调用getAdviceClass()方法分析出是什么类型的Advice,获取到一个adviceDefinition对象
getAdviceClass()
这个方法其实与刚刚介绍过的isAdviceNode()判断的类型是完全一致的

继续给刚刚获取到的adviceDefinition对象设置属性值
- 设置
aspectName属性和declarationOrder属性
- 设置
returning、throwing、arg-name这3个属性(先判断,有则设置)
- 设置构造函数的入参变量
- Method
- AspectJExpressionPointcut
- AspectInstanceFactory
然后解析<point-cut>节点

parsePointcutProperty()

至此,方法createAdviceDefinition()执行结束,返回一个AbstractBeanDefinition类型的对象adviceDef。我们也来回答下介绍方法前的问题:这些生成的RootBeanDefinition对象具体都是哪些类呢?

methodDefinition:MethodLocatingFactoryBean
aspectFactoryDef:SimpleBeanFactoryAwareAspectInstanceFactory
adviceDef:AspectJMethodBeforeAdvice
adviceDefinition:AspectJPointcutAdvisor
回到方法parseAspect()中,将当前解析过的beanDefinition(advisorDefinition)添加进集合beanDefinitions中

接着进入下一轮循环♻️,继续解析列表中的节点
第二次循环执行完成在parseContext对象的readerContext -> reader -> registry -> beanDefinitionMap属性中又多了一个AspectJPointcutAdvisor对象(AspectJPointcutAdvisor#1),嘿嘿没错每完成一次循环就会多一个~~0、1、2……递增

循环结束后,返回到parse()方法中,由于我在XML配置文件(如下图)中加了两个aspect标签🏷️,所以childElts里有两个Element,于是会再按上面👆得大致流程再执行一遍

全部遍历完成后一路返回
完成撒个花(。・ω・。)ノ🎉
转载自:https://juejin.cn/post/7176434721826537530