重庆网站建设快速建站,个人公众号申请要钱吗,帝国cms做企业网站,做脚本从网站引流Spring的事务属于逻辑事务。不是物理事务。 Spring并不直接管理事务#xff0c;而是提供了多种事务管理器#xff0c;它们将事务管理的职责委托给JDBC或者JTA等持久化机制所提供的相关平台框架的事务来实现。例如JDBC的事物管理器就是DataSourceTransactionManager。 Spr…Spring的事务属于逻辑事务。不是物理事务。 Spring并不直接管理事务而是提供了多种事务管理器它们将事务管理的职责委托给JDBC或者JTA等持久化机制所提供的相关平台框架的事务来实现。例如JDBC的事物管理器就是DataSourceTransactionManager。 Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager
public interface PlatformTransactionManager {TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;void commit(TransactionStatus status) throws TransactionException;void rollback(TransactionStatus status) throws TransactionException;
}通过这个接口Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器但是具体的实现就是各个平台自己的事情了。所以Spring事务管理的一个优点就是为不同的事务API提供一致的编程模型。
Spring Boot 使用事务非常简单需要EnableTransactionManagement和Transactional配合使用。首先使用注解EnableTransactionManagement 开启事务支持后然后在Service方法上添加注解Transactional便可。EnableTransactionManagement启注解事务管理等同于xml配置方式的 tx:annotation-driven /。
首先是EnableTransactionManagement类
Target(ElementType.TYPE)
Retention(RetentionPolicy.RUNTIME)
Documented
Import(TransactionManagementConfigurationSelector.class)
public interface EnableTransactionManagement {这里会import TransactionManagementConfigurationSelector类
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelectorEnableTransactionManagement {Overrideprotected String[] selectImports(AdviceMode adviceMode) {switch (adviceMode) {case PROXY:// 默认就是 PROXYreturn new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};case ASPECTJ:return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};default:return null;}}
}selectImports会返回两个类AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration。 AutoProxyRegistrar的作用就是向BeanFactory注册InfrastructureAdvisorAutoProxyCreator.class。而InfrastructureAdvisorAutoProxyCreator继承自AbstractAdvisorAutoProxyCreator就是让容器支持了AOP。 ProxyTransactionManagementConfiguration会加载关键的几个bean
Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {Bean(name TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {BeanFactoryTransactionAttributeSourceAdvisor advisor new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource());advisor.setAdvice(transactionInterceptor());advisor.setOrder(this.enableTx.IntegergetNumber(order));return advisor;}BeanRole(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource();}BeanRole(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor() {TransactionInterceptor interceptor new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource());if (this.txManager ! null) {interceptor.setTransactionManager(this.txManager);}return interceptor;}}BeanFactoryTransactionAttributeSourceAdvisor实现了 PointcutAdvisor 接口组合了TransactionAttributeSourcePointcut。AnnotationTransactionAttributeSource解析事务类得到事务配置相关信息TransactionInterceptor事务拦截器实现了 Advice、MethodInterceptor 接口。TransactionInterceptor是个环绕增强在目标方法执行前开启事务执行完目标方法后进行事务提交或者回滚
事务代理类的创建
了解Spring AOP应该会熟悉这段代码 public static boolean canApply(Advisor advisor, Class? targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}else if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca (PointcutAdvisor) advisor;return canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {// It doesnt have a pointcut so we assume it applies.return true;}}在前面 BeanFactoryTransactionAttributeSourceAdvisor 类该类实现了 PointcutAdvisor 接口其中的切面 pointcut 便是通过 TransactionAttributeSourcePointcut 来实现的。
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {private TransactionAttributeSource transactionAttributeSource;private final TransactionAttributeSourcePointcut pointcut new TransactionAttributeSourcePointcut() {Overrideprotected TransactionAttributeSource getTransactionAttributeSource() {return transactionAttributeSource;}};
}调用路径会到TransactionAttributeSourcePointcut的matches方法该方法根据能否可以从目标 bean 中得到 TransactionAttribute 来判断是否匹配的。
public boolean matches(Method method, Nullable Class? targetClass) {if (targetClass ! null TransactionalProxy.class.isAssignableFrom(targetClass)) {return false;}TransactionAttributeSource tas getTransactionAttributeSource();return (tas null || tas.getTransactionAttribute(method, targetClass) ! null);
}上面的tas即AnnotationTransactionAttributeSource。AnnotationTransactionAttributeSource父类AbstractFallbackTransactionAttributeSource实现了getTransactionAttribute方法
public TransactionAttribute getTransactionAttribute(Method method, Nullable Class? targetClass) {if (method.getDeclaringClass() Object.class) {return null;}// 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.//重点获取事务属性TransactionAttribute txAttr computeTransactionAttribute(method, targetClass);// Put it in the cache.if (txAttr null) {this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);}else {String methodIdentification ClassUtils.getQualifiedMethodName(method, targetClass);if (txAttr instanceof DefaultTransactionAttribute) {((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);}if (logger.isDebugEnabled()) {logger.debug(Adding transactional method methodIdentification with attribute: txAttr);}this.attributeCache.put(cacheKey, txAttr);}return txAttr;}
}
再看看computeTransactionAttribute方法
protected TransactionAttribute computeTransactionAttribute(Method method, Nullable Class? targetClass) {// Dont allow no-public methods as required.if (allowPublicMethodsOnly() !Modifier.isPublic(method.getModifiers())) {return null;}// 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.Method specificMethod AopUtils.getMostSpecificMethod(method, targetClass);// First try is the method in the target class.//先查找目标方式是否有事务属性TransactionAttribute txAttr findTransactionAttribute(specificMethod);if (txAttr ! null) {return txAttr;}// Second try is the transaction attribute on the target class.//再查找目标类是否有事务属性txAttr findTransactionAttribute(specificMethod.getDeclaringClass());if (txAttr ! null ClassUtils.isUserLevelMethod(method)) {return txAttr;}if (specificMethod ! method) {// Fallback is to look at the original method.txAttr findTransactionAttribute(method);if (txAttr ! null) {return txAttr;}// Last fallback is the class of the original method.txAttr findTransactionAttribute(method.getDeclaringClass());if (txAttr ! null ClassUtils.isUserLevelMethod(method)) {return txAttr;}}return null;
}
从上面可知方法级别上的注解会覆盖类级别上的注解两个findTransactionAttribute方法都在AnnotationTransactionAttributeSource实现
protected TransactionAttribute findTransactionAttribute(Method method) {return determineTransactionAttribute(method);
}protected TransactionAttribute findTransactionAttribute(Class? clazz) {return determineTransactionAttribute(clazz);
}
再看看determineTransactionAttribute方法
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {for (TransactionAnnotationParser annotationParser : this.annotationParsers) {TransactionAttribute attr annotationParser.parseTransactionAnnotation(ae);if (attr ! null) {return attr;}}return null;
}annotationParsers集合包含了3个类分别是SpringTransactionAnnotationParser、JtaTransactionAnnotationParser、Ejb3TransactionAnnotationParser。分别解析不同包的注解这里的解析类是SpringTransactionAnnotationParser其parseTransactionAnnotation方法
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement ae) {AnnotationAttributes attributes AnnotatedElementUtils.findMergedAnnotationAttributes(ae, Transactional.class, false, false);if (attributes ! null) {return parseTransactionAnnotation(attributes);}else {return null;}
}以上代码讲解析目标元素上Transactional注解的相关信息然后封装成AnnotationAttributes类其继承LinkedHashMap。
看看parseTransactionAnnotation方法 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));ArrayListRollbackRuleAttribute rollBackRules new ArrayListRollbackRuleAttribute();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;}切面实现
TransactionInterceptor 实现了方法拦截器 MethodInterceptor 接口用于对业务类进行事务增强。TransactionInterceptor 的 invoke 方法主要是调用了父类 TransactionAspectSupport 的 invokeWithinTransaction 方法。 Overridepublic Object invoke(final MethodInvocation invocation) throws Throwable {Class? targetClass (invocation.getThis() ! null ? AopUtils.getTargetClass(invocation.getThis()) : null);return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {Overridepublic Object proceedWithInvocation() throws Throwable {return invocation.proceed();}});}protected Object invokeWithinTransaction(Method method, Class? targetClass, final InvocationCallback invocation) throws Throwable {// 获取事务配置信息final TransactionAttribute txAttr getTransactionAttributeSource().getTransactionAttribute(method, targetClass);// 获取事务管理器final PlatformTransactionManager tm determineTransactionManager(txAttr);final String joinpointIdentification methodIdentification(method, targetClass, txAttr);// 同步操作if (txAttr null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {// 创建事务类TransactionInfo txInfo createTransactionIfNecessary(tm, txAttr, joinpointIdentification);Object retVal null;try {// 环绕增强触发链条上的下一个拦截器最终会调用目标类retVal invocation.proceedWithInvocation();} catch (Throwable ex) {// 出现异常则回滚completeTransactionAfterThrowing(txInfo, ex);throw ex;} finally {cleanupTransactionInfo(txInfo);}commitTransactionAfterReturning(txInfo);return retVal;} else {// 省略异步操作原理类似}}invoke 方法里主要做以下几件事
获取事务属性获取事务管理器创建事务执行目标方法遇到异常则回滚正常结束则提交。
创建事务的是TransactionAspectSupport#createTransactionIfNecessary()方法该方法的调用代码比较多主要摘取比较重要的看一下
---TransactionAspectSupport:createTransactionIfNecessary();---AbstractPlatformTransactionManager:getTransaction();---AbstractPlatformTransactionManager:doGetTransaction();---AbstractPlatformTransactionManager:doBegin();---DataSource:getConnection();---TransactionSynchronizationManager.bindResource();
参考
https://blog.csdn.net/wang704987562/article/details/88913808 https://blog.csdn.net/ai_xiangjuan/article/details/79687560 https://blog.csdn.net/u012562943/article/details/78333153 https://www.coder4.com/archives/5917 https://blog.csdn.net/dslztx/article/details/46636079