Spring声明式事务控制原理之声明式事务的重要组件(注解实现)以及之间关系

实现声明式事务只需要两个注解即可完成:@EnableTransactionManagement和@Transactional。下面就探究一下这两个注解究竟做了什么。

@Transactional注解大家比较熟悉,作用在方法上用来显式声明事务,可以通过属性指定事务的隔离级别,传播行为,什么异常回滚什么异常不回滚等。

主要还是探究一下@EnableTransactionManagement注解

进入EnableTransactionManagement注解类发现首先这个类通过@Import帮Spring以注解解析的方式引入了TransactionManagementConfigurationSelector

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

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as
	 * opposed to standard Java interface-based proxies ({@code false}). The default is
	 * {@code false}. <strong>Applicable only if {@link #mode()} is set to
	 * {@link AdviceMode#PROXY}</strong>.
	 * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
	 * Spring-managed beans requiring proxying, not just those marked with
	 * {@code @Transactional}. For example, other beans marked with Spring's
	 * {@code @Async} annotation will be upgraded to subclass proxying at the same
	 * time. This approach has no negative impact in practice unless one is explicitly
	 * expecting one type of proxy vs another, e.g. in tests.
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate how transactional advice should be applied.
	 * <p><b>The default is {@link AdviceMode#PROXY}.</b>
	 * Please note that proxy mode allows for interception of calls through the proxy
	 * only. Local calls within the same class cannot get intercepted that way; an
	 * {@link Transactional} annotation on such a method within a local call will be
	 * ignored since Spring's interceptor does not even kick in for such a runtime
	 * scenario. For a more advanced mode of interception, consider switching this to
	 * {@link AdviceMode#ASPECTJ}.
	 */
	AdviceMode mode() default AdviceMode.PROXY;

	/**
	 * Indicate the ordering of the execution of the transaction advisor
	 * when multiple advices are applied at a specific joinpoint.
	 * <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.
	 */
	// 默认最大int,,目的做方法最后执行的横切逻辑,将其他切面的横切逻辑也纳入,保证事务的原子性
	int order() default Ordered.LOWEST_PRECEDENCE;

}

进入TransactionManagementConfigurationSelector,这个类⼜向容器中导⼊了两个重要的组件AutoProxyRegistrar、ProxyTransactionManagementConfiguration

// AdviceModeImportSelector 实现了selectImports接口,实现了String[] selectImports(AnnotationMetadata importingClassMetadata);方法
	//此方法返回类的全限定名,返回的类将会注册到Spring容器中
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) {
    
    
			case PROXY:
				//AutoProxyRegistrar注册生成代理类的bean后置处理器
				//ProxyTransactionManagementConfiguration注册处理事务的advisor(通知器)
				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.进入AutoProxyRegistrar, AutoProxyRegistrar 类的 registerBeanDefinitions ⽅法中⼜注册了⼀个组件

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
    

	private final Log logger = LogFactory.getLog(getClass());

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
    
		boolean candidateFound = false;
		Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
		for (String annType : annTypes) {
    
    
			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
			if (candidate == null) {
    
    
				continue;
			}
			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实现了SmartInstantiationAwareBeanPostProcessor是个bean的后置处理器
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
    
    
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}
		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));
		}
	}

}

进入registerAutoProxyCreatorIfNecessary方法发现注册的后置处理器InfrastructureAdvisorAutoProxyCreator它实现SmartInstantiationAwareBeanPostProcessor,说明这是⼀个后置处理器,⽽且跟spring AOP 开启@EnableAspectJAutoProxy 时注册的 AnnotationAwareAspectJProxyCreator实现的是同⼀个接⼝,所以说,声明式事务是 springAOP 思想的⼀种应⽤

2.下面进入ProxyTransactionManagementConfiguration,见@Configuration值此类是个配置类,主要作用是向Spring中注入BeanFactoryTransactionAttributeSourceAdvisor(事务通知器/切面)

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    
    

	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
    
    
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		//  向事务通知器中注⼊ 属性解析器 transactionAttributeSource
		advisor.setTransactionAttributeSource(transactionAttributeSource());
		//  向事务增强器中注⼊ 事务拦截器 transactionInterceptor
		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() {
    
    
		TransactionInterceptor interceptor = new TransactionInterceptor();
		interceptor.setTransactionAttributeSource(transactionAttributeSource());
		if (this.txManager != null) {
    
    
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

进入BeanFactoryTransactionAttributeSourceAdvisor,Advisor两大组成部分是1.切点PointCut。2.通知Advice(连接点+横切逻辑;在SpringAOP中用于实现MethodInterceptor的invoke方法);

BeanFactoryTransactionAttributeSourceAdvisor的两大重要组件

1.属性解析器 TransactionAttributeSource(主要作用解析某方法中是否包含@Transactional,解析Transactional注解的各个属性封装成配置类备用)
2.务拦截器 TransactionInterceptor(实现MethodInterceptor的invoke方法,封装了横切逻辑 :设置事务自动提交fasle、事务提交、事务发生异常回滚)

其中BeanFactoryTransactionAttributeSourceAdvisor的PointCut也是根据TransactionAttributeSource属性解析器来判断一个类的某个方法是否切点,从而判断一个类是否要进行事务AOP处理创建代理类

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
    
    

	@Nullable
	private TransactionAttributeSource transactionAttributeSource;

	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
    
    
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
    
    
			return transactionAttributeSource;
		}
	};


	/**
	 * Set the transaction attribute source which is used to find transaction
	 * attributes. This should usually be identical to the source reference
	 * set on the transaction interceptor itself.
	 * @see TransactionInterceptor#setTransactionAttributeSource
	 */
	public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
    
    
		this.transactionAttributeSource = transactionAttributeSource;
	}

	/**
	 * Set the {@link ClassFilter} to use for this pointcut.
	 * Default is {@link ClassFilter#TRUE}.
	 */
	public void setClassFilter(ClassFilter classFilter) {
    
    
		this.pointcut.setClassFilter(classFilter);
	}

	@Override
	public Pointcut getPointcut() {
    
    
		return this.pointcut;
	}

}

进入事务属性解析器 TransactionAttributeSource

AnnotationTransactionAttributeSource.class
// 事务属性解析器集合(包括Spring的解析器、jpa的解析器)
private final Set<TransactionAnnotationParser> annotationParsers;

进入Spring的事务属性解析器

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
    
    

	@Override
	@Nullable
	// 判断方法中是否含有@Transaction注解
	public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
    
    
		AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
				element, Transactional.class, false, false);
		if (attributes != null) {
    
    
			return parseTransactionAnnotation(attributes);
		}
		else {
    
    
			return null;
		}
	}

	public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
    
    
		return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
	}
	// 解析@Transaction注解的各个属性封装成配置类备用
	protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
    
    
		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"));
		rbta.setQualifier(attributes.getString("value"));

		List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
		for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
    
    
			rollbackRules.add(new RollbackRuleAttribute(rbRule));
		}
		for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
    
    
			rollbackRules.add(new RollbackRuleAttribute(rbRule));
		}
		for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
    
    
			rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
		}
		for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
    
    
			rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
		}
		rbta.setRollbackRules(rollbackRules);

		return rbta;
	}


	@Override
	public boolean equals(Object other) {
    
    
		return (this == other || other instanceof SpringTransactionAnnotationParser);
	}

	@Override
	public int hashCode() {
    
    
		return SpringTransactionAnnotationParser.class.hashCode();
	}

}

进入务拦截器 TransactionInterceptor的invoke方法

TransactionInterceptor.class
	public Object invoke(MethodInvocation invocation) throws Throwable {
    
    
		// Work out the target class: may be {@code null}.
		// The TransactionAttributeSource should be passed the target class
		// as well as the method, which may be from an interface.
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
		// 带有事务处理的方法执行
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

进入TransactionAspectSupport#invokeWithinTransaction方法

TransactionAspectSupport.class
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {
    
    

		// If the transaction attribute is null, the method is non-transactional.
		// 1。获取事务属性解析器ProxyTransactionManagementConfiguration中注入
		TransactionAttributeSource tas = getTransactionAttributeSource();
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		// 2.获取事务管理器
		final PlatformTransactionManager tm = determineTransactionManager(txAttr);
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
    
    
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

			Object retVal;
			try {
    
    
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				// 3.执行原方法
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
    
    
				// target invocation exception
				// 4.如果目标方法剖出异常执行回滚操作,并且抛出异常
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
    
    
				cleanupTransactionInfo(txInfo);
			}
			// 5.如果目标方法正常执行执行事务提交操作。
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}

		else {
    
    
			final ThrowableHolder throwableHolder = new ThrowableHolder();

			// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
			try {
    
    
				Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
    
    
					TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
					try {
    
    
						return invocation.proceedWithInvocation();
					}
					catch (Throwable ex) {
    
    
						if (txAttr.rollbackOn(ex)) {
    
    
							// A RuntimeException: will lead to a rollback.
							if (ex instanceof RuntimeException) {
    
    
								throw (RuntimeException) ex;
							}
							else {
    
    
								throw new ThrowableHolderException(ex);
							}
						}
						else {
    
    
							// A normal return value: will lead to a commit.
							throwableHolder.throwable = ex;
							return null;
						}
					}
					finally {
    
    
						cleanupTransactionInfo(txInfo);
					}
				});

				// Check result state: It might indicate a Throwable to rethrow.
				if (throwableHolder.throwable != null) {
    
    
					throw throwableHolder.throwable;
				}
				return result;
			}
			catch (ThrowableHolderException ex) {
    
    
				throw ex.getCause();
			}
			catch (TransactionSystemException ex2) {
    
    
				if (throwableHolder.throwable != null) {
    
    
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
					ex2.initApplicationException(throwableHolder.throwable);
				}
				throw ex2;
			}
			catch (Throwable ex2) {
    
    
				if (throwableHolder.throwable != null) {
    
    
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
				}
				throw ex2;
			}
		}
	}

本文主要讲了声明式事务的重要组件以及之间关系,下篇文章会讲述各个组件在事务实现SpringAOP中的作用体现

猜你喜欢

转载自blog.csdn.net/yangxiaofei_java/article/details/112128858