欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring事务处理流程

程序员文章站 2022-07-12 17:03:00
...

这里讲述的是以@Transactional注解方式配置Spring事务的原理。

我们启用事务注解的时候,往往配置如下:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

<tx:annotation-driven transaction-manager="txManager" />

在Spring中,annotation-driven是用来开启注解支持的,前面添加名字空间,如tx:或者mvc:之类的,后面可以选填一些属性,这是我们需要了解的,具体属性值情况如下:

1、transaction-manager:指定到现有的PlatformTransactionManager bean的引用,通知会使用该引用。默认值为"transactionManager" 
2、mode:指定Spring事务管理框架创建通知bean的方式。可用的值有proxy和aspectj。默认值为proxy,表示通知对象是个JDK代理;后者表示Spring AOP会使用AspectJ创建代理。 
3、order:指定创建的切面的顺序。只要目标对象有多个通知就可以使用该属性。 
4、proxy-target-class:该属性如果为true就表示你想要代理目标类而不是bean所实现的所有接口。默认值为"false" 。

先来看看下面的Spring是如何处理<tx:annotation-driven transaction-manager="txManager" />标签的,先是org.springframework.beans.factory.xml.BeanDefinitionParserDelegate来处理标签,通过parseCustomElement()方法找到对应名字空间处理器,也即org.springframework.transaction.config.TxNamespaceHandler这个类来处理tx名字空间的标签的:

public class TxNamespaceHandler extends NamespaceHandlerSupport {
	static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";
	static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";

	static String getTransactionManagerName(Element element) {
		return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?
				element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);
	}

	@Override
	public void init() {
		registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
	}
}

真正处理的类型是org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser,具体的方法如下:

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

这里我们使用的是默认mode="proxy",也就是使用jdk提供的代理方式,这个函数始终返回null这点要注意。那么现在就要看看AnnotationDrivenBeanDefinitionParser中的静态内部类中的configureAutoProxyCreator()方法做了什么,这里也可以借鉴下使用静态内部类的情景,这个静态内部类只有一个静态方法,显然作者这里更多的体现的是封装思想以及面向对象编程思想。

private static class AopAutoProxyConfigurer {

	public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
		AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

		String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
		if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
			Object eleSource = parserContext.extractSource(element);

			// Create the TransactionAttributeSource definition.
			RootBeanDefinition sourceDef = new RootBeanDefinition(
					"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
			sourceDef.setSource(eleSource);
			sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

			// Create the TransactionInterceptor definition.
			RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
			interceptorDef.setSource(eleSource);
			interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			registerTransactionManager(element, interceptorDef);
			interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
			String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

			// Create the TransactionAttributeSourceAdvisor definition.
			RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
			advisorDef.setSource(eleSource);
			advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
			advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
			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);
		}
	}
}

这里看到通过硬编码的方式实例化了几个类到IOC容器中。