再分析完AOP之后,趁热打铁,再分析一下Spring的事务处理。
因为一直都是使用SpringBoot,所以用@EnableTransactionManagement和@Transactional就可以实现简单的例子,但是感觉不太直观,所以本文采用xml的配置来分析事务。
首先贴个简单的配置文件,包含支持十五注解的标签,还有事务管理器和一个半成品dataSource。
1 2 3 4 5 6 7 8 9 10 11 12
| <tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="customTxService" class="com.demo.CustomTxService"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> </bean>
|
定义一个事务方法,这里面的mapper随便写的。
1 2 3 4 5 6 7 8 9 10 11
| public class CustomTxService {
@Transactional public int sum(int num) { int result = customMapper.insert(num); int i = 1 / 0; return result; } }
|
最后方法调用:
1 2 3
| ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-tx.xml"); CustomTxService bean = context.getBean("customTxService", CustomTxService.class); bean.sum(2)
|
首先要解析xml中的自定义标签:<tx:annotation-driven transaction-manager=”txManager”/>
找到org.springframework.transaction.config.TxNamespaceHandler类:
1 2 3 4 5 6
| @Override public void init() { registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser()); registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser()); registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser()); }
|
即AnnotationDrivenBeanDefinitionParser类负责解析annotation-driven标签:
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
|
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { registerTransactionalEventListenerFactory(parserContext); String mode = element.getAttribute("mode"); if ("aspectj".equals(mode)) { registerTransactionAspect(element, parserContext); if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) { registerJtaTransactionAspect(element, parserContext); } } else { AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext); } return null; }
|
因为我这没有配置mode,所以走代理模式:
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
|
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);
RootBeanDefinition sourceDef = new RootBeanDefinition( "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"); sourceDef.setSource(eleSource); sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
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);
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); } } }
|
总的来说就是用Spring AOP实现了事务的统一管理,通过注册InfrastructureAdvisorAutoProxyCreator,在bean初始化的时候对bean进行增强。
通过InfrastructureAdvisorAutoProxyCreator获取到当前的Advisor:BeanFactoryTransactionAttributeSourceAdvisor,和当前的Pointcut:TransactionAttributeSourcePointcut。
在调用TransactionAttributeSourcePointcut的match方法来获取要增强的方法,即被被@Transactional修饰的方法,这里会使用AnnotationTransactionAttributeSource的getTransactionAttribute解析。
TransactionAttributeSourcePointcut的match方法用于过滤当前bean是否需要增强:
1 2 3 4 5 6 7 8 9 10
| @Override public boolean matches(Method method, Class<?> targetClass) { if (TransactionalProxy.class.isAssignableFrom(targetClass) || PlatformTransactionManager.class.isAssignableFrom(targetClass) || PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) { return false; } TransactionAttributeSource tas = getTransactionAttributeSource(); return (tas == null || tas.getTransactionAttribute(method, targetClass) != null); }
|
AnnotationTransactionAttributeSource解析在其父类AbstractFallbackTransactionAttributeSource中:
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
|
@Override @Nullable public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) { if (method.getDeclaringClass() == Object.class) { return null; }
Object cacheKey = getCacheKey(method, targetClass); TransactionAttribute cached = this.attributeCache.get(cacheKey); if (cached != null) { if (cached == NULL_TRANSACTION_ATTRIBUTE) { return null; } else { return cached; } } else { TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
if (txAttr == null) { this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE); } else { String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass); if (txAttr instanceof DefaultTransactionAttribute) { ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification); } if (logger.isTraceEnabled()) { logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr); } this.attributeCache.put(cacheKey, txAttr); } return txAttr; } }
|
进入核心方法:
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
|
@Nullable protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) { if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; }
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
TransactionAttribute txAttr = findTransactionAttribute(specificMethod); if (txAttr != null) { return txAttr; }
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; }
if (specificMethod != method) { txAttr = findTransactionAttribute(method); if (txAttr != null) { return txAttr; } txAttr = findTransactionAttribute(method.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } }
return null; }
|
从这可知会去解析方法上的注解,如果没有的话解析类上的注解。
findTransactionAttribute(Method method)与findTransactionAttribute(Class<?> clazz)最终会调用AnnotationTransactionAttributeSource中的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Nullable protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) { for (TransactionAnnotationParser annotationParser : this.annotationParsers) { TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element); if (attr != null) { return attr; } } return null; }
|
这里以SpringTransactionAnnotationParser为例子:
1 2 3 4 5 6 7 8 9 10 11 12
| @Override @Nullable public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) { AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes( element, Transactional.class, false, false); if (attributes != null) { return parseTransactionAnnotation(attributes); } else { return null; } }
|
就分析到这一层好了,最终过滤出了当前的bean是否应该被增强。
总结一下本篇的流程:
- 用一个假的例子来示范事务的使用;
- 解析xml文件,解析tx:annotation-driven/标签
- 注入InfrastructureAdvisorAutoProxyCreator便于在目标bean实例化的时候增强
- 配置Advisor:BeanFactoryTransactionAttributeSourceAdvisor,和Pointcut:TransactionAttributeSourcePointcut,用于匹配和处理事务增强操作。
- 使用AnnotationTransactionAttributeSource来解析@Transaction注解的方法或者类
下一篇在分析到底是如何事务增强的。