我们在spring使用事务有三种方式,第一种使用xml配置的方式配置,第二种使用注解的方式配置,第三种使用编程的方式。 我们首先从xml配置开始
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
上面是一段常见的xml配置事务的方式,而解析这些标签的命名空间处理器是由TxNamespaceHandler实现的,其注册的标签解析器如下
public void init() {
//解析advice标签
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
//解析注解事务标签
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
//解析jta分布式事务标签
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
按照惯例,我们首先了解xml配置事务的分析,然后在分析注解事务,第一步,分析TxAdviceBeanDefinitionParser,下面是它的类图
public final BeanDefinition org.springframework.beans.factory.xml.AbstractBeanDefinitionParser.parse(Element element, ParserContext parserContext) {
//具体的实现由子类实现
//(*1*)
AbstractBeanDefinition definition = parseInternal(element, parserContext);
//BeanDefinition不为空,并且当前BeanDefinition不是被包含的BeanDefinition
if (definition != null && !parserContext.isNested()) {
try {
//解析id,获取beanName
String id = resolveId(element, definition, parserContext);
if (!StringUtils.hasText(id)) {
parserContext.getReaderContext().error(
"Id is required for element '" + parserContext.getDelegate().getLocalName(element)
+ "' when used as a top-level tag", element);
}
String[] aliases = null;
//解析别名
if (shouldParseNameAsAliases()) {
String name = element.getAttribute(NAME_ATTRIBUTE);
if (StringUtils.hasLength(name)) {
aliases = StringUtils.trimArrayElements(StringUtils.commaDelimitedListToStringArray(name));
}
}
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition, id, aliases);
//注册BeanDefinition
registerBeanDefinition(holder, parserContext.getRegistry());
//触发事件,循环调用事件监听器
if (shouldFireEvents()) {
BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder);
postProcessComponentDefinition(componentDefinition);
parserContext.registerComponent(componentDefinition);
}
}
catch (BeanDefinitionStoreException ex) {
parserContext.getReaderContext().error(ex.getMessage(), element);
return null;
}
}
return definition;
}
//(*1*)
protected final AbstractBeanDefinition org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser.parseInternal(Element element, ParserContext parserContext) {
//创建GenericBeanDefinition(这是一个通用BeanDefinition,常用于xml配置的bean)构建器
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
//获取父配置的id名
String parentName = getParentName(element);
if (parentName != null) {
//设置父配置id名
builder.getRawBeanDefinition().setParentName(parentName);
}
//这个方法由子类TxAdviceBeanDefinitionParser实现,返回TransactionInterceptor事务拦截器,这是一个实现了MethodInterceptor
//接口的类
Class<?> beanClass = getBeanClass(element);
if (beanClass != null) {
builder.getRawBeanDefinition().setBeanClass(beanClass);
}
else {
String beanClassName = getBeanClassName(element);
if (beanClassName != null) {
builder.getRawBeanDefinition().setBeanClassName(beanClassName);
}
}
//设置数据的来源
builder.getRawBeanDefinition().setSource(parserContext.extractSource(element));
//如果当前BeanDefinition是被包含的,那么继承包含BeanDefinition的生命周期
if (parserContext.isNested()) {
// Inner bean definition must receive same scope as containing bean.
builder.setScope(parserContext.getContainingBeanDefinition().getScope());
}
//设置默认的懒加载设置
if (parserContext.isDefaultLazyInit()) {
// Default-lazy-init applies to custom bean definitions as well.
builder.setLazyInit(true);
}
//这才是真正解析标签元素数据的地方
doParse(element, parserContext, builder);
return builder.getBeanDefinition();
}
我们从上面的代码看到,spring准备构建的BeanDefinition是TransactionInterceptor,这个拦截器实现了MethodInterceptor,这拦截器的逻辑我们放在后面分析,我继续往下分析advice标签的解析
protected void org.springframework.transaction.config.TxAdviceBeanDefinitionParser.doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
//设置transactionManager属性,解析元素的transaction-manager属性,如果没有,就使用默认的transactionManager作为事务名
builder.addPropertyReference("transactionManager", TxNamespaceHandler.getTransactionManagerName(element));
//获取attributes标签
List<Element> txAttributes = DomUtils.getChildElementsByTagName(element, ATTRIBUTES_ELEMENT);
//attributes标签只允许一个
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);
//解析并创建属性源BeanDefinition
//(*1*)
RootBeanDefinition attributeSourceDefinition = parseAttributeSource(attributeSourceElement, parserContext);
//设置事务属性源
builder.addPropertyValue("transactionAttributeSource", attributeSourceDefinition);
}
else {
// Assume annotations source.
//如果没有设置事务属性,那么只好使用注解事务属性源
builder.addPropertyValue("transactionAttributeSource",
new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"));
}
}
//(*1*)
private RootBeanDefinition parseAttributeSource(Element attrEle, ParserContext parserContext) {
//获取method标签元素
List<Element> methods = DomUtils.getChildElementsByTagName(attrEle, METHOD_ELEMENT);
//用于维护方法名表达式与对应事务属性的关系,RuleBasedTransactionAttribute的继承结构如下图
ManagedMap<TypedStringValue, RuleBasedTransactionAttribute> transactionAttributeMap =
new ManagedMap<TypedStringValue, RuleBasedTransactionAttribute>(methods.size());
transactionAttributeMap.setSource(parserContext.extractSource(attrEle));
for (Element methodEle : methods) {
//获取name属性,比如本例中的save*,update*等
String name = methodEle.getAttribute(METHOD_NAME_ATTRIBUTE);
//使用TypedStringValue进行包装
TypedStringValue nameHolder = new TypedStringValue(name);
//设置当前name值的来源
nameHolder.setSource(parserContext.extractSource(methodEle));
//构建基于规则的事务属性对象
RuleBasedTransactionAttribute attribute = new RuleBasedTransactionAttribute();
//解析propagation获取事务传播属性
String propagation = methodEle.getAttribute(PROPAGATION_ATTRIBUTE);
//解析isolation获取隔离级别
String isolation = methodEle.getAttribute(ISOLATION_ATTRIBUTE);
//解析timeout获取事务超时时间
String timeout = methodEle.getAttribute(TIMEOUT_ATTRIBUTE);
//read-only是否只读
String readOnly = methodEle.getAttribute(READ_ONLY_ATTRIBUTE);
//设置传播属性值(转换成int类型)
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));
}
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)) {
//获取rollback-for属性值,按逗号分割,包装成RollbackRuleAttribute对象存储到rollbackRules集合中
String rollbackForValue = methodEle.getAttribute(ROLLBACK_FOR_ATTRIBUTE);
addRollbackRuleAttributesTo(rollbackRules,rollbackForValue);
}
//no-rollback-for 设置不需要回滚的异常类型
if (methodEle.hasAttribute(NO_ROLLBACK_FOR_ATTRIBUTE)) {
//获取no-rollback-for属性值,按逗号分割,包装成NoRollbackRuleAttribute对象存储到rollbackRules集合中
String noRollbackForValue = methodEle.getAttribute(NO_ROLLBACK_FOR_ATTRIBUTE);
addNoRollbackRuleAttributesTo(rollbackRules,noRollbackForValue);
}
//设置回滚规则
attribute.setRollbackRules(rollbackRules);
//储存到transactionAttributeMap集合中
transactionAttributeMap.put(nameHolder, attribute);
}
//构建NameMatchTransactionAttributeSource事务属性源
RootBeanDefinition attributeSourceDefinition = new RootBeanDefinition(NameMatchTransactionAttributeSource.class);
attributeSourceDefinition.setSource(parserContext.extractSource(attrEle));
//将刚才获取的事务属性map设置到事务属性源中
attributeSourceDefinition.getPropertyValues().add("nameMap", transactionAttributeMap);
return attributeSourceDefinition;
}
上面一段代码中为每个method标签创建了一个RuleBasedTransactionAttribute对象,将method标签上的属性都设置到这个对象中,所以TransactionAttribute就是一个用于承载事务属性数据的模型,下面是RuleBasedTransactionAttribute的继承结构
TransactionDefinition 主要定义一些全局静态属性,比如事务传播属性值,隔离级别值,定义获取隔离级别,事务传播属性,超时时间的能力,看到这个TransactionDefinition,就应该想到BeanDefinition,都是用于承载属性定义的模型对象
TransactionAttribute 增加了一些qualifier,qualifier我们以前在分析bean的时候分析过,这个东西是用来筛选事务管理器,比如通过当前事务定义的qualifier值与对应事务管理器中@Qualifier进行对比是否符合条件,或者beanName对比等,忘记的同学可以翻看bean创建的那一章节,这里就不过多的赘述了
DefaultTransactionDefinition 提供一些扩展属性定义,比如代表事务传播的前缀,隔离级别的前缀等等
DefaultTransactionAttribute 实现了一些基本方法,比如是否定义哪些异常能够回滚,默认是RuntimeException,Error
RuleBasedTransactionAttribute 支持自定义异常的回滚
我们看到spring把每个方法对应的RuleBasedTransactionAttribute以方法匹配模式为key,RuleBasedTransactionAttribute为值的方式存储到了一个map中,最后设置到一个叫NameMatchTransactionAttributeSource的对象中,这个类的继承结构如下
TransactionAttributeSource 定义通过方法,对应class类获取事务属性的能力
NameMatchTransactionAttributeSource TransactionAttributeSource的实现类,通过方法名匹配来获取对应的事务属性
下面是NameMatchTransactionAttributeSource的getTransactionAttribute方法
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
//如果不是用户定义的方法,直接返回,比如说桥方法,虚拟机生成的,groovy.lang.GroovyObject类的方法
if (!ClassUtils.isUserLevelMethod(method)) {
return null;
}
// Look for direct name match.
//获取方法名
String methodName = method.getName();
//直接通过方法获取看看能不能获取
TransactionAttribute attr = this.nameMap.get(methodName);
//不能获取,那么就只能通过简单匹配的方式获取了,简单匹配xxx*,xxx*yyy,*xxx这种模式
if (attr == null) {
// Look for most specific name match.
String bestNameMatch = null;
for (String mappedName : this.nameMap.keySet()) {
if (isMatch(methodName, mappedName) &&
(bestNameMatch == null || bestNameMatch.length() <= mappedName.length())) {
attr = this.nameMap.get(mappedName);
bestNameMatch = mappedName;
}
}
}
return attr;
}
advice标签解析的时候创建了一个TransactionInterceptor的BeanDefinition,并给这个BeanDefinition注入事务属性源,事务管理器,下面是xml配置的advice标签的解析过程时序图和事务拦截器的类图
xml配置解析advice标签的分析到此结束,接下来继续看annotation-driven标签的解析,对应的解析器为AnnotationDrivenBeanDefinitionParser
<tx:annotation-driven transaction-manager="txManager" />
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
public BeanDefinition org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser.parse(Element element, ParserContext parserContext) {
//注册事务事件监听器TransactionalEventListenerFactory
//事件监听工厂在refresh方法的
//org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(ConfigurableListableBeanFactory)
//中初始化完非懒加载单例bean后调用,用于创建ApplicationListener
//创建一个ApplicationListenerMethodTransactionalAdapter监听器
registerTransactionalEventListenerFactory(parserContext);
String mode = element.getAttribute("mode");
//如果模式是aspectj,那么spring将启用aspectj框架进行切面代理,使用特殊的编译器在编译器进行代理
if ("aspectj".equals(mode)) {
// mode="aspectj"
registerTransactionAspect(element, parserContext);
}
else {
//这是我们常用的模式,使用JDK或者cglib代理
// mode="proxy"
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}
对于注解的aop有两种模式,一种是aspectj,另一种是proxy,proxy是我们默认使用的,aspectj需要aspectj特殊编译器(ajc)的支持,在编译期进行aop代理,感兴趣的同学可以去研究研究它的语法。文档地址:https://www.eclipse.org/aspectj/doc/released/progguide/index.html 或者一个入门aspectj的博客:https://blog.mythsman.com/2017/12/21/1/
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
//注册InfrastructureAdvisorAutoProxyCreator后置处理器
AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);
//beanName
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);
//使用生成的beanName进行注册
String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);
// Create the TransactionInterceptor definition.
//创建TransactionInterceptor的BeanDefinition,这个拦截器我们在分析xml配置的时候讲到过,其细节不再赘述
RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
interceptorDef.setSource(eleSource);
interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//给TransactionInterceptor设置事务管理器属性
registerTransactionManager(element, interceptorDef);
//给TransactionInterceptor设置事务属性源
interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
//注册到BeanFactory
String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);
// Create the TransactionAttributeSourceAdvisor definition.
//创建关于事务的advisor
RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
advisorDef.setSource(eleSource);
//标记为基础设施角色,这种角色类型的类不会被后置处理
advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//设置事务属性源
advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
//设置通知拦截的beanName
advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
if (element.hasAttribute("order")) {
advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
}
//注册到BeanFactory
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解析annotation-driven时向BeanFactory中注入了后置处理器InfrastructureAdvisorAutoProxyCreator,事务属性源AnnotationTransactionAttributeSource,通知TransactionInterceptor,通知器BeanFactoryTransactionAttributeSourceAdvisor,对应事务这个advisor它所持有的切点是一个继承了StaticMethodMatcherPointcut的类,所以可以想象到对应的ClassFilter是一个ClassFilter.TRUE,AnnotationTransactionAttributeSource我们参考前面xml配置的NameMatchTransactionAttributeSource就可以猜测到它具有通过某种方式获取TransactionAttribute的能力。 下面我们先来看看InfrastructureAdvisorAutoProxyCreator的类图
我们发现这个类的继承结构和我们前面分析注解aop后置处理器AnnotationAwareAspectJAutoProxyCreator很像,InfrastructureAdvisorAutoProxyCreator只是 重写了isEligibleAdvisorBean,initBeanFactory方法,其他的和AnnotationAwareAspectJAutoProxyCreator一样,所以对于它怎么获取advisor的,这不再过多的赘述了,现在我们来看看AnnotationTransactionAttributeSource是怎么获取TransactionAttribute的
public TransactionAttribute org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.getTransactionAttribute(Method method, Class<?> targetClass) {
// First, see if we have a cached value.
Object cacheKey = getCacheKey(method, targetClass);
//从缓存中获取
Object cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return (TransactionAttribute) cached;
}
}
else {
// We need to work it out.
//(*1*)
TransactionAttribute txAtt = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAtt == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
if (logger.isDebugEnabled()) {
Class<?> classToLog = (targetClass != null ? targetClass : method.getDeclaringClass());
logger.debug("Adding transactional method '" + classToLog.getSimpleName() + "." +
method.getName() + "' with attribute: " + txAtt);
}
this.attributeCache.put(cacheKey, txAtt);
}
return txAtt;
}
}
//(*1*)
protected TransactionAttribute org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource.computeTransactionAttribute(Method method, Class<?> targetClass) {
// Don't allow no-public methods as required.
//如果不允许代理非publi的方法,那么直接跳过
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// Ignore CGLIB subclasses - introspect the actual user class.
//获取用户定义的类,如果是CGLIB代理的类,那么getSuperClass
Class<?> userClass = ClassUtils.getUserClass(targetClass);
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
//获取指定userClass中的方法对象
Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
// If we are dealing with method with generic parameters, find the original method.
//找到被桥的方法
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
// First try is the method in the target class.
//首先从目标方法上寻找@Transaction并解析
TransactionAttribute txAtt = findTransactionAttribute(specificMethod);
if (txAtt != null) {
return txAtt;
}
// Second try is the transaction attribute on the target class.
//如果第一步失败,那么从定义这个方法的类上面找
txAtt = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAtt != null) {
return txAtt;
}
//如果还是失败,那么从原始指定的方法上找,要是还是失败,那么从原始方法定义的类上找
if (specificMethod != method) {
// Fallback is to look at the original method.
txAtt = findTransactionAttribute(method);
if (txAtt != null) {
return txAtt;
}
// Last fallback is the class of the original method.
return findTransactionAttribute(method.getDeclaringClass());
}
//实在找不到,返回null
return null;
}
spring的代码之所以优秀除了使用各种设计模式之外,他们在代码的处理上也是职责清晰,不同职责的代码放在不同的方法中,避免一个方法处理过多的职责,如果把方法看成是一个接口的话,那么这就是设计模式中接口单一原则
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
if (ae.getAnnotations().length > 0) {
//一般产常用的的注解解析器是SpringTransactionAnnotationParser,其他两个分别是JtaTransactionAnnotationParser(用于jta分布式事务注解
// javax.transaction.Transactional),
//Ejb3TransactionAnnotationParser(用于ejb)
//这里我们只分析SpringTransactionAnnotationParser的解析
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
if (attr != null) {
return attr;
}
}
}
return null;
}
解析spring事务注解@org.springframework.transaction.annotation.Transactional
public TransactionAttribute org.springframework.transaction.annotation.SpringTransactionAnnotationParser.parseTransactionAnnotation(AnnotatedElement ae) {
//获取@Transactional的合并属性名-》属性值,在spring中元注解与注解具有父子级关系,我们在分析spring通过注解扫描
//bean时较为详细的探讨这个问题,感兴趣的同学可以翻开之前的文章,或者自己研究代码
AnnotationAttributes attributes = AnnotatedElementUtils.getMergedAnnotationAttributes(ae, Transactional.class);
if (attributes != null) {
//(*1*)
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
//(*1*)
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
//又看到我们熟悉的RuleBasedTransactionAttribute了,我们在分析xml配置aop的时候对其较详细的进行了讲解
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
//获取事务传播属性
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
//获取事务隔离级别
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
//设置事务超时时间
rbta.setTimeout(attributes.getNumber("timeout").intValue());
//设置是否只读
rbta.setReadOnly(attributes.getBoolean("readOnly"));
//设置Qualifier筛选器
rbta.setQualifier(attributes.getString("value"));
ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();
//解析回滚异常
Class<?>[] rbf = attributes.getClassArray("rollbackFor");
for (Class<?> rbRule : rbf) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
//解析回滚异常
String[] rbfc = attributes.getStringArray("rollbackForClassName");
for (String rbRule : rbfc) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
//解析非回滚异常
Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
for (Class<?> rbRule : nrbf) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
//解析非回滚异常
String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
for (String rbRule : nrbfc) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
//设置事务回滚异常规则集合
rbta.getRollbackRules().addAll(rollBackRules);
return rbta;
}
ok,注解解析事务属性的分析就到这,下面分析事务拦截才是重头戏。不管是xml还是注解他们都使用了一个叫做TransactionInterceptor的通知拦截器
public Object invoke(final MethodInvocation invocation) throws Throwable {
//获取被代理类的Class对象
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
//在事务中调用方法
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
//驱动链条执行下一个拦截器
return invocation.proceed();
}
});
}
事务调用方法
protected Object org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
//使用事务属性源获取事务属性,xml配置的事务源将以简单匹配的方式匹配方法(xxx*,xxx*yyy,*xxx)获取事务属性
//注解事务属性源解析@Transaction注解的获取事务属性
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
//获取事务管理器,从BeanFactory中获取,并通过@Qualifier筛选
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
//连接点标识 className + "." + methodName
final String joinpointIdentification = methodIdentification(method, targetClass);
//处理没有事务属性和管理器不是回调方式管理器的事务,我们本例中使用的管理器是DataSourceTransactionManager
//它不是一个支持回调的事务
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
//创建事务信息
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
//继续向下一个拦截器执行
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
//发生异常,需要进行事务的回滚,恢复挂起事务等操作
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
//清理到当前线程中的事务信息
cleanupTransactionInfo(txInfo);
}
//提交事务,恢复挂起事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
。。。。。。省略回调事务管理器的代码,在后面分析
}
我们站在事务门外看了下,大致了解到spring执行事务其实就是使用aop的环绕,抛出异常通知的结合。下一节,我们到事务的家里坐坐客,了解下spring是如果创建事务的。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?