Spring 声明式事务 各阶段的流程图

声明式事务底层原理是基于AOP的, 换句话说比先学习了AOP, 才能看得懂其源码流程

一、Spring 声明式事务的入口点

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseCustomElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

/**
	 * 拿到元素的命名空间URI,  再从 XmlReaderContext 找到对应的 NamespaceHandler 调用解析 `parse`方法解析到 BeanDefinition 返回
	 *
	 * Parse a custom element (outside the default namespace).
	 * @param ele the element to parse
	 * @param containingBd the containing bean definition (if any)
	 * @return the resulting bean definition
	 */
	@Nullable
	public BeanDefinition parseCustomElement(Element ele,  @Nullable BeanDefinition containingBd) {
		//拿到 命名空间URI
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
			return null;
		}
		/**
		 * 拿到对应命名空间的 Handler ,  this.readerContext 是在
		 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions(org.w3c.dom.Document,  org.springframework.core.io.Resource) 创建的
		 * 		它会从父属性的 namespaceHandlerResolver 中拿到命名空间处理器,  调用NamespaceHandler#parse 进行解析
		 * 		它默认读取的配置是 `META-INF/spring.handlers` 文件
		 *
		 * 对于注解的支持:
		 * 配置<context:annotation-config />的标签以表示启用注解,  这里会拿到 org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser 进行处理
		 * 往 beanfactory 注册了四个 BeanDefinition,  重点是以下这两个
		 * org.springframework.context.annotation.internalConfigurationAnnotationProcessor
		 * org.springframework.context.annotation.internalAutowiredAnnotationProcessor
		 * 实现了 BeanDefinitionRegistryPostProcessor 在这里进行扩展
		 *
		 * 对于AOP的支持:
		 * 在XML中配置 <aop:..> 启用Aop标签,  在解析XML自定义标签时,  这里会拿到 AopNamespaceHandler 命名空间处理器,  其内部的 ConfigBeanDefinitionParser 做了两件事
		 * 1. 注册了一个对AOP处理的 BeanDefinition 名称是
		 * org.springframework.aop.config.internalAutoProxyCreator 对应的类有根据情况有三个可能
		 *  InfrastructureAdvisorAutoProxyCreator.class, 
		 * AspectJAwareAdvisorAutoProxyCreator.class,   AnnotationAwareAspectJAutoProxyCreator.class
		 * 它们都是实现 InstantiationAwareBeanPostProcessor接口的
		 * 2. 解析 <aop:config> 标签的子元素
		 * org.springframework.aop.config.ConfigBeanDefinitionParser#parse
		 *
		 *  对于TX事务的支持:
		 * org.springframework.transaction.config.TxNamespaceHandler
		 * 在XML中配置 <tx:..> 启用tx标签,  在解析XML自定义标签时,  这里会拿到 TxNamespaceHandler 命名空间处理器,  其主要工作就是注册事务相关的标签的解析器
		 *  <tx:advice> 标签解析器:解析事务通知(核心事务规则配置) TxAdviceBeanDefinitionParser
		 *  <tx:annotation-driven> 标签解析器:开启注解驱动的事务 AnnotationDrivenBeanDefinitionParser
		 */
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]",  ele);
			return null;
		}
		// 调用 Handler 解析,  返回的是 BeanDefinition;
		return handler.parse(ele,  new ParserContext(this.readerContext,  this,  containingBd));
	}

对于XML入口点

org.springframework.transaction.config.TxNamespaceHandler

package org.springframework.transaction.config;  
  
import org.w3c.dom.Element;  
  
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;  
  
/**  
 * {@code NamespaceHandler} allowing for the configuration of  
 * declarative transaction management using either XML or using annotations. * * <p>This namespace handler is the central piece of functionality in the * Spring transaction management facilities and offers two approaches * to declaratively manage transactions. * * <p>One approach uses transaction semantics defined in XML using the * {@code <tx:advice>} elements,  the other uses annotations  
 * in combination with the {@code <tx:annotation-driven>} element.  
 * Both approached are detailed to great extent in the Spring reference manual. * * @author Rob Harrop  
 * @author Juergen Hoeller  
 * @since 2.0  
 */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() {  
       //  <tx:advice> 标签解析器:负责解析XML <tx:advice> 事务标签配置 TxAdviceBeanDefinitionParser       registerBeanDefinitionParser("advice",  new TxAdviceBeanDefinitionParser());  
       //  <tx:annotation-driven> 标签解析器:负责解析注解相关的事务配置 AnnotationDrivenBeanDefinitionParser       registerBeanDefinitionParser("annotation-driven",  new AnnotationDrivenBeanDefinitionParser());  
       // JTA 规范的分布式事务管理器(管理跨多个资源的事务) TODO  
       registerBeanDefinitionParser("jta-transaction-manager",  new JtaTransactionManagerBeanDefinitionParser());  
    }  
}

启用事务注解支持

当前启用注解<tx:annotation-driven> 配置时, 其解析处理器: org.springframework.transaction.config.AnnotationDrivenBeanDefinitionParser 根据 mode 参数

  • 默认 mode="proxy"(代理模式): 这是最常用的方式, 基于 Spring AOP 动态代理实现, 也是解析器的核心处理逻辑
  • mode="aspectj"(AspectJ 模式): 基于 AspectJ 编译期 / 类加载期织入, 需额外注册 AspectJ 事务切面(TransactionAspect), 适用于需要拦截内部方法调用的场景
/**
	 * Parses the {@code <tx:annotation-driven/>} tag. Will
	 * {@link AopNamespaceUtils#registerAutoProxyCreatorIfNecessary register an AutoProxyCreator}
	 * with the container as necessary.
	 */
	@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);
			if (ClassUtils.isPresent("jakarta.transaction.Transactional",  getClass().getClassLoader())) {
				registerJtaTransactionAspect(element,  parserContext);
			}
		}
		else {
			// mode="proxy"
			AopAutoProxyConfigurer.configureAutoProxyCreator(element,  parserContext);
		}
		return null;
	}

注册几个 BeanDefinition, 其中构建事务增强器(BeanFactoryTransactionAttributeSourceAdvisor)

  • Pointcut(切点): 默认匹配所有标注 @Transactional 的类 / 方法(由 TransactionAttributeSourcePointcut 实现)
  • Advice(通知): 即 TransactionInterceptor(事务拦截器)
  • TransactionAttributeSource(注解解析器):即 AnnotationTransactionAttributeSource, 负责解析 @Transactional 注解的属性(传播行为、隔离级别等)
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);
				
				/**  
				 * 其中构建事务增强器(BeanFactoryTransactionAttributeSourceAdvisor)  
				 * - **Pointcut(切点)**: 默认匹配所有标注 `@Transactional` 的类 / 方法(由 `TransactionAttributeSourcePointcut` 实现)  
				 * - **Advice(通知)**: 即 `TransactionInterceptor`(事务拦截器)  
				 * - **TransactionAttributeSource(注解解析器)**:即 `AnnotationTransactionAttributeSource`, 负责解析 `@Transactional` 注解的属性(传播行为、隔离级别等)。  
				 */
				// 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);
			}
		}
	}

对于注解的入口

package org.yang.learn.spring.tx;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import org.yang.learn.spring.dto.Book;
import org.yang.learn.spring.dto.User;
/**
 * ${Description}
 * @author yangfh
 * @date 2023-12-14 21:20
 **/
@EnableTransactionManagement
public class TXMain {
 
	@Transactional
	public static void main(String[] args) throws Exception {
		System.out.println("==========================================================");
		//ApplicationContext context = new ClassPathXmlApplicationContext("application-tx.xml");
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("org.yang.learn.spring.tx");
		BookService bookService = context.getBean("bookService", BookService.class);
		Book book = new Book();
		book.setName("30秒精通javascript,一分钟精通java");
		book.setCode(""+System.currentTimeMillis());
//		bookService.insertWithTransaction(book );
		bookService.insertWithNoTransaction(book);
		System.out.println("bookService = "+bookService);
		System.out.println("bookService getList = "+bookService.getList());
		System.out.println("==========================================================");
	}
}

二、事务相关的 BeanDefinition 解析过程 (XML)

org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal

public abstract class AbstractSingleBeanDefinitionParser extends AbstractBeanDefinitionParser {
 
	/**
	 * Creates a {@link BeanDefinitionBuilder} instance for the
	 * {@link #getBeanClass bean Class} and passes it to the
	 * {@link #doParse} strategy method.
	 * @param element the element that is to be parsed into a single BeanDefinition
	 * @param parserContext the object encapsulating the current state of the parsing process
	 * @return the BeanDefinition resulting from the parsing of the supplied {@link Element}
	 * @throws IllegalStateException if the bean {@link Class} returned from
	 * {@link #getBeanClass(org.w3c.dom.Element)} is {@code null}
	 * @see #doParse
	 *
	 */
	@Override
	protected final AbstractBeanDefinition parseInternal(Element element,  ParserContext parserContext) {
		/**
		 *
		 *
		 * 1. 解析 <tx:advice ... 标签 封装为`GenericBeanDefinition`
		 * 其名称和class为org.springframework.transaction.interceptor.TransactionInterceptor
		 * 注意这个 TransactionInterceptor 实现了MethodInterceptor相当于是个Advice
		 *
		 * org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser
		 * #parseInternal(org.w3c.dom.Element,  org.springframework.beans.factory.xml.ParserContext)
		 *
		 * org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#parseInternal
		 *
		 * 2. 解析 <tx:attributes> 属性标签,  并将这些属性附加到上面的 GenericBeanDefinition中
		 * org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser
		 * #doParse(org.w3c.dom.Element,  org.springframework.beans.factory.xml.ParserContext,  org.springframework.beans.factory.support.BeanDefinitionBuilder)
		 *
		 */
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
		String parentName = getParentName(element);
		if (parentName != null) {
			builder.getRawBeanDefinition().setParentName(parentName);
		}
		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 containingBd = parserContext.getContainingBeanDefinition();
		if (containingBd != null) {
			// Inner bean definition must receive same scope as containing bean.
			builder.setScope(containingBd.getScope());
		}
		if (parserContext.isDefaultLazyInit()) {
			// Default-lazy-init applies to custom bean definitions as well.
			builder.setLazyInit(true);
		}
		doParse(element,  parserContext,  builder);
		return builder.getBeanDefinition();
	}

三、事务增强 相关的对象创建

四、事务增强 相关的方法调用流程