在分析通过Aop实现事务之前最好先回顾下基础知识:https://blog.csdn.net/qq_23536449/article/details/97630249;三种实现事务的方式:https://blog.csdn.net/qq_23536449/article/details/97645090
1.TransactionInterceptor.java它是一个Advice,实现了对方法的增强逻辑;即方法事务的提交回滚操作都是通过它。
- TransactionAspectSupport:事务切面的基类,他持有PlatformTransactionManager(事务管理器)和TransactionAttributeSource(事务属性配置;可以通过@Transaction(xx=,xx=,xx=)或者<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT"/>),实现对事务的回滚、提交操作。
- TransactionInterceptor:用于使用通用Spring事务基础结构进行声明式事务管理({@link org.springframework.transaction.PlatformTransactionManager});它实现了MethodInterceptor接口,所以最后在调用代理对象方法前后都会执行invoke()方法。实现事务的关键类。
2.新的标签的加入必然少不了NamespaceHandlerSupport类TxNamespaceHandler.java
3.TxAdviceBeanDefinitionParser.doParse方法;解析那些使用tx:advice声明的事务(特殊的aop advice所以也需要配置aop:config使用)。该方法创建了TransactionInterceptor.class的beanDefinition,并配置了transactionManger,和事务的一些属性transactionAttributeSource
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
//创建TransactionInterceptor 的beanDefinition
//解析 transaction-manager 属性,没有的话给个默认值transactionManager
builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));
List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT);
if (txAttributes.size() > 1) {
parserContext.getReaderContext().error(
"Element <attributes> is allowed at most once inside element <advice>", element);
}
else if (txAttributes.size() == 1) {
// Using attributes source.
Element attributeSourceElement = txAttributes.get(0);
RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
}
else {
// Assume annotations source.
// 注释事务来源
builder.addPropertyValue("transactionAttributeSource",
new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"));
}
}
private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) {
//获取所有method标签元素
List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT);
ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap =
new ManagedMap<TypedStringValue, RuleBasedTransactionAttribute>(methods.size());
//source嘿嘿
transactionAttributeMap.setSource(parserContext.extractSource(attrEle));
for (Element methodEle : methods) {
//获取method name 标签元素
String name = methodEle.getAttribute(METHOD_NAME_ATTRIBUTE);
TypedStringValue nameHolder = new TypedStringValue(name);
nameHolder.setSource(parserContext.extractSource(methodEle));
RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute();
//传播行为属性
String propagation = methodEle.getAttribute(PROPAGATION_ATTRIBUTE);
//事务隔离级别属性
String isolation = methodEle.getAttribute(ISOLATION_ATTRIBUTE);
//事务超时时长属性
String timeout = methodEle.getAttribute(TIMEOUT_ATTRIBUTE);
String readOnly = methodEle.getAttribute(READ_ONLY_ATTRIBUTE);
if (StringUtils.hasText(propagation)) {
attribute.setPropagationBehaviorName(RuleBasedTransactionAttribute.PREFIX_PROPAGATION + propagation);
}
if (StringUtils.hasText(isolation)) {
attribute.setIsolationLevelName(RuleBasedTransactionAttribute.PREFIX_ISOLATION + isolation);
}
if (StringUtils.hasText(timeout)) {
try {
attribute.setTimeout(Integer.parseInt(timeout));
}
//解析timeout属性出错
catch (NumberFormatException ex) {
parserContext.getReaderContext().error("Timeout must be an integer value: [" + timeout + "]", methodEle);
}
}
if (StringUtils.hasText(readOnly)) {
attribute.setReadOnly(Boolean.valueOf(methodEle.getAttribute(READ_ONLY_ATTRIBUTE)));
}
List<RollbackRuleAttribute> rollbackRules = new LinkedList<RollbackRuleAttribute>();
//rollback-for 属性,可以指定多个
if (methodEle.hasAttribute(ROLLBACK_FOR_ATTRIBUTE)) {
String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE);
addRollbackRuleAttributesTo(rollbackRules,rollbackForValue);
}
//是否有no-rollback-for属性
if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) {
String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE);
addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue);
}
attribute.setRollbackRules(rollbackRules);
//放到ManagedMap中
transactionAttributeMap.put(nameHolder, attribute);
}
//创建NameMatchTransactionAttributeSource 的beanDefinition
RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class);
attributeSourceDefinition.setSource(parserContext.extractSource(attrEle));
attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap);
return attributeSourceDefinition;
}
//回滚属性
private void addRollbackRuleAttributesTo(List<RollbackRuleAttribute> rollbackRules, String rollbackForValue) {
String[] exceptionTypeNames = StringUtils.commaDelimitedListToStringArray(rollbackForValue);
for (String typeName : exceptionTypeNames) {
rollbackRules.add(new RollbackRuleAttribute(StringUtils.trimWhitespace(typeName)));
}
}
//不回滚的属性
private void addNoRollbackRuleAttributesTo(List<RollbackRuleAttribute> rollbackRules, String noRollbackForValue) {
String[] exceptionTypeNames = StringUtils.commaDelimitedListToStringArray(noRollbackForValue);
for (String typeName : exceptionTypeNames) {
rollbackRules.add(new NoRollbackRuleAttribute(StringUtils.trimWhitespace(typeName)));
}
}
这里需要注意的是transactionAttributeSource,是一个map,key对应-开启事务的方法名称,value-这个开启事务的方法对应的事务相关属性配置;通过RuleBasedTransactionAttribute类保存。(后面会用到这个map获取匹配方法的事务属性,实现Spring的事务处理)
- TransactionDefinition:定义符合Spring的事务属性的接口;该接口包含事务的常量;比如隔离级别定义、传播特性定义;然后一些与事务相关的属性方法getPropagationBehavior()返回传播行为、getIsolationLevel()隔离级别、getTimeout()事务超时时间、getName()事务名称。
- TransactionAttribute:此接口将{@code rollbackOn}规范添加到{@link TransactionDefinition}。 * 由于自定义{@code rollbackOn}仅适用于AOP,因此它位于与AOP相关的事务子包中
- DefaultTransactionDefinition:提供bean风格的配置和合理的默认值 (PROPAGATION_REQUIRED,ISOLATION_DEFAULT,TIMEOUT_DEFAULT,readOnly = false)
- DefaultTransactionAttribute:Spring的常见事务属性实现。 默认RuntimeException或者Error回滚
- RuleBasedTransactionAttribute:TransactionAttribute实现,通过应用许多回滚规则来确定给定异常是否应该导致事务回滚如果没有规则与异常相关,则其行为类似于DefaultTransactionAttribute(回滚运行时异常)
tx:advice其实是一个特殊的Aop增强,所以他也需要和advisor一起才有意义。正确使用如下:
<!--定义事务增强点-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* org.springframework.study.day16.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
4.AnnotationDrivenBeanDefinitionParser.parse方法;解析<tx:annotation-driven transaction-manager="transactionManager"/>
/**
* Parses the {@code <tx:annotation-driven/>} tag. Will
* {@link AopNamespaceUtils#registerAutoProxyCreatorIfNecessary register an AutoProxyCreator}
* with the container as necessary.
*/
@Override
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;
}
/**
* Inner class to just introduce an AOP framework dependency when actually in proxy mode.
*/
private static class AopAutoProxyConfigurer {
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
//注册InfrastructureAdvisorAutoProxyCreator类型的bean 同 Aop
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
//获取txAdvisorBeanName internalTransactionAdvisor
String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
//是否包含该internalTransactionAdvisor 对应的beanDefinition
if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
//获取element的source
Object eleSource = parserContext.extractSource(element);
// Create the TransactionAttributeSource definition.
// 创建TransactionAttributeSource定义;该bean用于从类或方法上读取@Transaction注解和其属性
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.
//创建TransactionInterceptor定义。
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.
//创建BeanFactoryTransactionAttributeSourceAdvisor定义
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);
}
}
}
对于开启事务的模式我们只关心proxy谢谢;所以我们把分析的中心放在AopAutoProxyConfigurer.configureAutoProxyCreator方法
- a.AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);方法,在刚开始分析Aop源码已经分析过了,其实就是注册一个auto-proxy creator
- b.创建AnnotationTransactionAttributeSource的beanDefinition并注册,关于AnnotationTransactionAttributeSource其实就是从读取@Transaction注释,并将属性保存到TransactionAttribute,其UML类图如下:
- TransactionAttributeSource:保存了给定方法的事务属性
- AbstractFallbackTransactionAttributeSource:{@link TransactionAttributeSource}的抽象实现,它缓存方法的事务属性并实现查找@Transacation注解的策略 * :1。特定的目标方法; 目标类; 接口方法; 4.声明类/接口
- AnnotationTransactionAttributeSource:实现{@link org.springframework.transaction.interceptor.TransactionAttributeSource}接口,用于处理JDK 1.5+注释格式的事务元数据;该类读取Spring的JDK 1.5+ {@link Transactional}注释,并向Spring的事务基础结构公开相应的事务属性. * 还支持JTA 1.2的{@link javax.transaction.Transactional}和EJB3的{@link javax.ejb.TransactionAttribute}注释(如果存在). * 此类还可以作为自定义TransactionAttributeSource的基类,或通过{@link TransactionAnnotationParser}策略进行自定义.
- c.创建TransactionInterceptor的beandefinition并注册,设置了transactionAttributeSource属性(由AnnotationTransactionAttributeSource解析注解数据产生)和transactionManager的BeanName
- d.创建实现Aop需要的advisor---BeanFactoryTransactionAttributeSourceAdvisor的beanDefinition
- BeanFactoryTransactionAttributeSourceAdvisor:由 {@link TransactionAttributeSource}驱动的advisor, 用于包含事务性方法的advice bean;可以这么理解,该advisor的advice为TransactionInterceptor,他的pointcut是根据TransactionAttributeSource创建的TransactionAttributeSourcePointcut,所以叫通过{@link TransactionAttributeSource}驱动的advisor,因为他的pointcut是由TransactionAttributeSource产生的呗。
- e.注册CompositeComponentDefinition