目录
  1. xml解析
spring事务(1) xml配置解析

xml解析

spring IoC容器的初始化时xml解析spring AOP的xml解析一样,spring事务部分的xml解析同样是在BeanDefinitionParserDelegate类的parseCustomElement方法中执行的,spring事务部分所对应的命名空间为http://www.springframework.org/schema/tx

里面对应的解析器如下:

元素名 解析器
advice TxAdviceBeanDefinitionParser
jta-transaction-manager JtaTransactionManagerBeanDefinitionParser
annotation-driven AnnotationDrivenBeanDefinitionParser

由于主要阅读的是注解方式的事务实现,其对应的标签元素为annotation-driven,那么它所对应的解析器即为AnnotationDrivenBeanDefinitionParser。

打开解析方法,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 该方法在org.springframework.transaction.config包下的
// AnnotationDrivenBeanDefinitionParser类中

public BeanDefinition parse(Element element, ParserContext parserContext) {
String mode = element.getAttribute("mode");
if ("aspectj".equals(mode)) {
// mode="aspectj"
registerTransactionAspect(element, parserContext);
}
else {
// mode="proxy"
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}

打开调试我们可以发现对于我们的xml配置,默认存在如下两个属性:

1
2
mode="proxy"
proxy-target-class="false"

对于proxy-target-class属性,如果有看过之前的AOP部分,就清楚true表示强制使用cglib作为代理实现方式。

其中mode属性为proxy表示使用代理的方式来实现事务,为aspectj则表示时用aspectj的方式来实现事务。其中代理的方式是通过spring AOP来实现的。至于proxy与aspectj的差异,可以查看这篇文章Java JDK代理、CGLIB、AspectJ代理分析比较

我们此处来看proxy的解析方式。

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
// 该方法在AnnotationDrivenBeanDefinitionParser类的内部类AopAutoProxyConfigurer中

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
// 注册AutoProxyCreator,用来生成代理的
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
String txAdvisorBeanName = "org.springframework.transaction.config.internalTransactionAdvisor";

// 如果还没有注册事务的通知(advice)
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
Object eleSource = parserContext.extractSource(element);

// 设置事务属性源为AnnotationTransactionAttributeSource
RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
sourceDef.setSource(eleSource);
sourceDef.setRole(2);
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

// 设置事务拦截器为TransactionInterceptor
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(2);
AnnotationDrivenBeanDefinitionParser.registerTransactionManager(element, interceptorDef);
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
advisorDef.setRole(2);
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);

// 设置通知的order
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}

// 注册通知
parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

// 注册组件
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
parserContext.registerComponent(compositeDef);
}

}

我们继续来看看其第一部分的注册AutoProxyCreator的源码,

1
2
3
4
5
6
7
8
9
10
// 此方法在AopNamespaceUtils类中

public static void registerAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {

BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
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
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
// 可以看到此处传入的参数为InfrastructureAdvisorAutoProxyCreator类
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

// 如果已经存在了AutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 取优先级大的
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}

// 如果还不存在AutoProxyCreator,
// 则将InfrastructureAdvisorAutoProxyCreator设置为AutoProxyCreator
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 此方法在AopNamespaceUtils类中

// 该方法就是用来设置是否强制使用cglib来生成代理,与AOP的解析部分相同
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {
if (sourceElement != null) {
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}

最后一个registerComponentIfNecessary是用来注册AutoProxyCreator组件的。

我们可以发现整个注册AutoProxyCreator其实就是使用了AOP,应该说在没有AOP的情况下,会创建一个自己的AOP。

那么我们最终对proxy的解析方式做一个梳理,如下:

  • 注册AutoProxyCreator(主要是用来创建代理的,具体作用可以详见spring AOP部分的博客。此处若是已经存在AutoProxyCreator,比如AOP的,则使用优先级高的那个)
  • 创建internalTransactionAdvisor
    • 其事务属性源设置为AnnotationTransactionAttributeSource
    • 通知(advice)设置为TransactionInterceptor
    • order设置为xml中配置的order属性
  • 将tx:annotation-driven注册为组件
文章作者: 谷河
文章链接: https://www.lyytaw.com/spring/spring_tx_xml_parse/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 谷河|BLOG