SpringAOP 源码之配置

开始

简单的 xml 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

<bean id="logUtil" class="com.devinx3.demo.aop.xml.util.LogUtil"/>
<bean class="com.devinx3.demo.aop.xml.service.DemoService"/>

<!-- 如果已经配置了 aop:config, 则无需此标签 -->
<!-- <aop:aspectj-autoproxy /> -->

<aop:config>
<aop:aspect ref="logUtil">
<aop:pointcut id="logPoint"
expression="execution( Object com.devinx3.demo.aop.xml.service.DemoService.* (..))"/>
<aop:around method="around" pointcut-ref="logPoint"/>
<aop:before method="start" pointcut-ref="logPoint"/>
<aop:after method="logFinally" pointcut-ref="logPoint"/>
<aop:after-returning method="stop" pointcut-ref="logPoint" returning="result"/>
<aop:after-throwing method="logException" pointcut-ref="logPoint" throwing="e"/>
</aop:aspect>
</aop:config>
</beans>

解析 AOP 配置文件

AopNamespaceHandler

定位: org.springframework.aop.config.AopNamespaceHandler

注册 aop 标签的解析器

1
2
3
4
5
6
7
8
public void init() {  
// In 2.0 XSD as well as in 2.5+ XSDs
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace in 2.5+
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}

config 标签解析器

定位: org.springframework.aop.config.ConfigBeanDefinitionParser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
// 注册自动代理模式创建器, AspectjAwareAdvisorAutoProxyCreator (aspectj-autoproxy)
configureAutoProxyCreator(parserContext, element);
// 解析 aop:config 子节点下的 aop:pointcut/aop:advice/aop:aspect
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
parsePointcut(elt, parserContext);
} else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
} else if (ASPECT.equals(localName)) {
parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
解析 pointcut 标签

解析 pointcut 并构造 AspectJExpressionPointcut 元信息, 注册到 ben 工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
private AbstractBeanDefinition parsePointcut(Element pointcutElement, ParserContext parserContext) {
// 切入点的唯一标识
String id = pointcutElement.getAttribute(ID);
// 获取切入点的表达式
String expression = pointcutElement.getAttribute(EXPRESSION);
AbstractBeanDefinition pointcutDefinition = null;
try {
// 采用栈保存切入点
this.parseState.push(new PointcutEntry(id));
// 创建切入点bean对象
// beanClass为AspectJExpressionPointcut.class。并且设置属性expression到该beanClass
pointcutDefinition = createPointcutDefinition(expression);
pointcutDefinition.setSource(parserContext.extractSource(pointcutElement));
String pointcutBeanName = id;
// 注册 BeanDefinition
if (StringUtils.hasText(pointcutBeanName)) {
parserContext.getRegistry().registerBeanDefinition(pointcutBeanName, pointcutDefinition);
} else {
// 生成 BeanDefinition 的名称
pointcutBeanName = parserContext.getReaderContext().registerWithGeneratedName(pointcutDefinition);
}
parserContext.registerComponent(
new PointcutComponentDefinition(pointcutBeanName, pointcutDefinition, expression));
}
finally {
// 创建后移除
this.parseState.pop();
}
return pointcutDefinition;
}
// 创建 pointcut 的 bean 元信息
protected AbstractBeanDefinition createPointcutDefinition(String expression) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(AspectJExpressionPointcut.class);
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanDefinition.setSynthetic(true);
beanDefinition.getPropertyValues().add(EXPRESSION, expression);
return beanDefinition;
}
解析 advice 标签

包含 around, before, after, after-returning, after-throwing

解析 pointcut 并构造 AspectJExpressionPointcut 元信息,
解析 around, before, after, after-returning, after-throwing 并构造 AspectJMethodBeforeAdvice, AspectJAfterAdvice, AspectJAfterReturningAdvice, AspectJAfterThrowingAdvice, AspectJAroundAdvice 元信息
同时构造 AspectJPointcutAdvisor 元信息,并注册到 bean 工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 解析通知类并注册到 bean 工厂(org.springframework.aop.aspectj.AspectJPointcutAdvisor)
private AbstractBeanDefinition parseAdvice(
String aspectName, int order, Element aspectElement, Element adviceElement, ParserContext parserContext,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {

try {
this.parseState.push(new AdviceEntry(parserContext.getDelegate().getLocalName(adviceElement)));

// create the method factory bean
// 解析 advice 节点中的 "method" 属性,并包装为 MethodLocatingFactoryBean 对象
RootBeanDefinition methodDefinition = new RootBeanDefinition(MethodLocatingFactoryBean.class);
methodDefinition.getPropertyValues().add("targetBeanName", aspectName);
methodDefinition.getPropertyValues().add("methodName", adviceElement.getAttribute("method"));
methodDefinition.setSynthetic(true);

// create instance factory definition
// 关联 aspectName,包装为 SimpleBeanFactoryAwareAspectInstanceFactory 对象
RootBeanDefinition aspectFactoryDef =
new RootBeanDefinition(SimpleBeanFactoryAwareAspectInstanceFactory.class);
aspectFactoryDef.getPropertyValues().add("aspectBeanName", aspectName);
aspectFactoryDef.setSynthetic(true);

// register the pointcut
// 涉及 point-cut 属性的解析,并结合上述的两个 bean 最终包装为 AbstractAspectJAdvice通知对象
AbstractBeanDefinition adviceDef = createAdviceDefinition(
adviceElement, parserContext, aspectName, order, methodDefinition, aspectFactoryDef,
beanDefinitions, beanReferences);

// configure the advisor
// 最终包装为 AspectJPointcutAdvisor 对象
RootBeanDefinition advisorDefinition = new RootBeanDefinition(AspectJPointcutAdvisor.class);
advisorDefinition.setSource(parserContext.extractSource(adviceElement));
advisorDefinition.getConstructorArgumentValues().addGenericArgumentValue(adviceDef);
if (aspectElement.hasAttribute(ORDER_PROPERTY)) {
advisorDefinition.getPropertyValues().add(
ORDER_PROPERTY, aspectElement.getAttribute(ORDER_PROPERTY));
}
// register the final advisor
parserContext.getReaderContext().registerWithGeneratedName(advisorDefinition);

return advisorDefinition;
}
finally {
this.parseState.pop();
}
}

创建通知 的 bean 元信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
private AbstractBeanDefinition createAdviceDefinition(
Element adviceElement, ParserContext parserContext, String aspectName, int order,
RootBeanDefinition methodDef, RootBeanDefinition aspectFactoryDef,
List<BeanDefinition> beanDefinitions, List<BeanReference> beanReferences) {

// 首先根据adviceElement节点分析出是什么类型的Advice
RootBeanDefinition adviceDefinition = new RootBeanDefinition(getAdviceClass(adviceElement, parserContext));
adviceDefinition.setSource(parserContext.extractSource(adviceElement));

// 设置aspectName属性和declarationOrder属性
adviceDefinition.getPropertyValues().add(ASPECT_NAME_PROPERTY, aspectName);
adviceDefinition.getPropertyValues().add(DECLARATION_ORDER_PROPERTY, order);

// 解析节点是否含有`returning`/`throwing`/`arg-names`,有则设置
if (adviceElement.hasAttribute(RETURNING)) {
adviceDefinition.getPropertyValues().add(
RETURNING_PROPERTY, adviceElement.getAttribute(RETURNING));
}
if (adviceElement.hasAttribute(THROWING)) {
adviceDefinition.getPropertyValues().add(
THROWING_PROPERTY, adviceElement.getAttribute(THROWING));
}
if (adviceElement.hasAttribute(ARG_NAMES)) {
adviceDefinition.getPropertyValues().add(
ARG_NAMES_PROPERTY, adviceElement.getAttribute(ARG_NAMES));
}

// 设置构造函数的入参变量
// Method/AspectJExpressionPointcut/AspectInstanceFactory三个入参
ConstructorArgumentValues cav = adviceDefinition.getConstructorArgumentValues();
cav.addIndexedArgumentValue(METHOD_INDEX, methodDef);

// 解析 pointcut 属性
Object pointcut = parsePointcutProperty(adviceElement, parserContext);
if (pointcut instanceof BeanDefinition) {
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcut);
beanDefinitions.add((BeanDefinition) pointcut);
}
else if (pointcut instanceof String) {
RuntimeBeanReference pointcutRef = new RuntimeBeanReference((String) pointcut);
cav.addIndexedArgumentValue(POINTCUT_INDEX, pointcutRef);
beanReferences.add(pointcutRef);
}
cav.addIndexedArgumentValue(ASPECT_INSTANCE_FACTORY_INDEX, aspectFactoryDef);

return adviceDefinition;
}
// 根据不同的标签使用对应的 advice
private Class<?> getAdviceClass(Element adviceElement, ParserContext parserContext) {
String elementName = parserContext.getDelegate().getLocalName(adviceElement);
if (BEFORE.equals(elementName)) {
return AspectJMethodBeforeAdvice.class;
}
else if (AFTER.equals(elementName)) {
return AspectJAfterAdvice.class;
}
else if (AFTER_RETURNING_ELEMENT.equals(elementName)) {
return AspectJAfterReturningAdvice.class;
}
else if (AFTER_THROWING_ELEMENT.equals(elementName)) {
return AspectJAfterThrowingAdvice.class;
}
else if (AROUND.equals(elementName)) {
return AspectJAroundAdvice.class;
}
else {
throw new IllegalArgumentException("Unknown advice kind [" + elementName + "].");
}
}
解析 advisor 标签

解析 advisor 并构造 DefaultBeanFactoryPointcutAdvisor 元信息, 注册到 ben 工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private void parseAdvisor(Element advisorElement, ParserContext parserContext) {
// 解析 <aop:advisor> 节点,最终创建的 beanClass 为 DefaultBeanFactoryPointcutAdvisor
// 另外 advice-ref 属性必须定义,其与内部属性 adviceBeanName 对应
AbstractBeanDefinition advisorDef = createAdvisorBeanDefinition(advisorElement, parserContext);
String id = advisorElement.getAttribute(ID);
try {
this.parseState.push(new AdvisorEntry(id));
String advisorBeanName = id;
// 注册到 bean 工厂
if (StringUtils.hasText(advisorBeanName)) {
parserContext.getRegistry().registerBeanDefinition(advisorBeanName, advisorDef);
}
else {
advisorBeanName = parserContext.getReaderContext().registerWithGeneratedName(advisorDef);
}
// 解析 pointcut 属性并赋值到 DefaultBeanFactoryPointcutAdvisor#pointcut 内部属性
Object pointcut = parsePointcutProperty(advisorElement, parserContext);
if (pointcut instanceof BeanDefinition) {
advisorDef.getPropertyValues().add(POINTCUT, pointcut);
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName, advisorDef, (BeanDefinition) pointcut));
}
else if (pointcut instanceof String) {
advisorDef.getPropertyValues().add(POINTCUT, new RuntimeBeanReference((String) pointcut));
parserContext.registerComponent(
new AdvisorComponentDefinition(advisorBeanName, advisorDef));
}
}
finally {
this.parseState.pop();
}
}