当前位置:   article > 正文

SpringBoot下@Transactional原理_springboot @transactional原理

springboot @transactional原理

一、@Transactional的使用

  • 加在方法上:方法内的所有操作处于一个事务中
  • 加在类上
    • 该类的所有public修饰的方法都具有共享事务属性
    • 如果方法和类上都有事务注解,方法上的事务注解优先

二、@Transactional原理

Springboot目前最为流行,它的约定大于配置的特性深受大家喜欢,注解驱动开发已成为主流。面向元数据遍历已经成为越来越多开发者的偏好,因此原理从Springboot的EnableTransactionManagement注解说起

1、@EnableTransactionManagement

表示开启事务管理

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
   

	boolean proxyTargetClass() default false;

	AdviceMode mode() default AdviceMode.PROXY;
    
	int order() default Ordered.LOWEST_PRECEDENCE;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

通过Import导入了TransactionManagementConfigurationSelector类,其中默认的AdviceMode为AdviceMode.PROXY,即默认使用JDK的动态代理生成代理类。

2、TransactionManagementConfigurationSelector

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
   

	/**
	 * Returns {@link ProxyTransactionManagementConfiguration} or
	 * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
	 * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
	 * respectively.
	 */
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
   
		switch (adviceMode) {
   
            //根据上面注解的默认配置,adviceMode默认为PROXY
			case PROXY:
				return new String[] {
   AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {
   determineTransactionAspectClass()};
			default:
				return null;
		}
	}

	private String determineTransactionAspectClass() {
   
		return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
				TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
				TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
	}
}
  • 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

TransactionManagementConfigurationSelector继承自AdviceModeImportSelector类,实现selectImports方法可以注入对应的bean,根据EnableTransactionManagement注解的默认配置,adviceMode默认为PROXY。所以这里会注入AutoProxyRegistrar和ProxyTransactionManagementConfiguration这两个类

  • AutoProxyRegistrar

    public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
         
    
    	private final Log logger = LogFactory.getLog(getClass());
    
    	/**
    	 * Register, escalate, and configure the standard auto proxy creator (APC) against the
    	 * given registry. Works by finding the nearest annotation declared on the importing
    	 * {@code @Configuration} class that has both {@code mode} and {@code proxyTargetClass}
    	 * attributes. If {@code mode} is set to {@code PROXY}, the APC is registered; if
    	 * {@code proxyTargetClass} is set to {@code true}, then the APC is forced to use
    	 * subclass (CGLIB) proxying.
    	 * <p>Several {@code @Enable*} annotations expose both {@code mode} and
    	 * {@code proxyTargetClass} attributes. It is important to note that most of these
    	 * capabilities end up sharing a {@linkplain AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME
    	 * single APC}. For this reason, this implementation doesn't "care" exactly which
    	 * annotation it finds -- as long as it exposes the right {@code mode} and
    	 * {@code proxyTargetClass} attributes, the APC can be registered and configured all
    	 * the same.
    	 */
    	@Override
    	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
         
    		boolean candidateFound = false;
            // 这里面需要特别注意的是:这里是拿到所有的注解类型~~~而不是只拿@EnableAspectJAutoProxy这个类型的
    		// 原因:因为mode、proxyTargetClass等属性会直接影响到代理得方式,而拥有这些属性的注解至少有:
    		// @EnableTransactionManagement、@EnableAsync、@EnableCaching等~~~~
    		// 甚至还有启用AOP的注解:@EnableAspectJAutoProxy它也能设置`proxyTargetClass`这个属性的值,因此也会产生关联影响~
    		Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
    		for (String annType : annTypes) {
         
    			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
    			if (candidate == null) {
         
    				continue;
    			}
                //获取mode和proxyTargetClass的属性
    			Object mode = candidate.get("mode");
    			Object proxyTargetClass = candidate.get("proxyTargetClass");
                //如果存在这两个属性且类型符合要求
    			if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
    					Boolean.class == proxyTargetClass.getClass()) {
         
    				candidateFound = true;
    				if (mode == AdviceMode.PROXY) {
         
                        //向容器注入的是一个InfrastructureAdvisorAutoProxyCreator,它主要是读取Advisor类,并对符合的bean进行二次代理
                        //如果出现多次的话,这里不是覆盖的形式,而是以第一次的为主
    					//当然它内部有做等级的提升之类的
    					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                        //看要不要强制使用CGLIB的方式(这个属性若出现多次,是会是覆盖的形式)
    					if ((Boolean) proxyTargetClass) {
         
    						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
    						return;
    					}
    				}
    			}
    		}
            
            //如果一个都没有找到则打印info日志
    		//可能是自己注入这个类,而不是使用注解去注入
    		if (!candidateFound && logger.isInfoEnabled()) {
         
    			String name = getClass().getSimpleName();
    			logger.info(String.format("%s was imported but no annotations were found " +
    					"having both 'mode' and 'proxyTargetClass' attributes of type " +
    					"AdviceMode and boolean respectively. This means that auto proxy " +
    					"creator registration and configuration may not have occurred as " +
    					"intended, and components may not be proxied as expected. Check to " +
    					"ensure that %s has been @Import'ed on the same class where these " +
    					"annotations are declared; otherwise remove the import of %s " +
    					"altogether.", name, name, name));
    		}
    	}
    
    }
    
    • 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
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    主要作用就是往Spring容器注入了一个自动代理创建器:org.springframework.aop.config.internalAutoProxyCreator,并且看看是采用CGLIB还是JDK代理

  • ProxyTransactionManagementConfiguration

    @Configuration(proxyBeanMethods = false)
    public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
         
    
    	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
    			TransactionAttributeSource transactionAttributeSource,
    			TransactionInterceptor transactionInterceptor) {
         
    		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
    		advisor.setTransactionAttributeSource(transactionAttributeSource);
    		advisor.setAdvice(transactionInterceptor);
    		if (this.enableTx != null) {
         
    			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
    		}
    		return advisor;
    	}
    
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	public TransactionAttributeSource transactionAttributeSource() {
         
    		return new AnnotationTransactionAttributeSource();
    	}
    
    	@Bean
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	public TransactionInterceptor transactionInterceptor(
    			TransactionAttributeSource transactionAttributeSource) {
         
    		TransactionInterceptor interceptor = new TransactionInterceptor();
    		interceptor.setTransactionAttributeSource(transactionAttributeSource);
    		if (this.txManager != null) {
         
    			interceptor.setTransactionManager(this.txManager);
    		}
    		return interceptor;
    	}
    }
    
    • 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

    这里是往容器中注入事务相关的bean

    • BeanFactoryTransactionAttributeSourceAdvisor:事务的核心,下面分析
    • TransactionAttributeSource:事务属性源
    • TransactionInterceptor:事务拦截器,它是个MethodInterceptor。(我们可以自定义个beanName一模一样的TransactionInterceptor来覆盖默认的事务拦截器)

    再看父类AbstractTransactionManagementConfiguration

    @Configuration
    public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
         
    
    	@Nullable
    	protected AnnotationAttributes enableTx;
    
    	/**
    	 * Default transaction manager, as configured through a {@link TransactionManagementConfigurer}.
    	 */
    	@Nullable
    	protected TransactionManager txManager;
    
    
    	@Override
    	public void setImportMetadata(AnnotationMetadata importMetadata) {
         
    		this.enableTx = AnnotationAttributes.fromMap(
    				importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
    		if (this.enableTx == null) {
         
    			throw new IllegalArgumentException(
    					"@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
    		}
    	}
    
        //这里可以通过配置文件注入一个默认的事务管理器
    	@Autowired(required = false)
    	void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
         
    		if (CollectionUtils.isEmpty(configurers)) {
         
    			return;
    		}
            //最多只允许配置一个
    		if (configurers.size() > 1) {
         
    			throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
    		}
    		TransactionManagementConfigurer configurer = configurers.iterator().next();
    		this.txManager = configurer.annotationDrivenTransactionManager();
    	}
    
        //注册一个监听器工厂,用以支持@TransactionalEventListener注解标注的方法,来监听事务相关的事件
    	@Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
    	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    	public static TransactionalEventListenerFac
    • 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
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号