目录
PlatformTransactionManager接口介绍:
spring-boot-autoconfigure.spring.factories中已导入事务自动装配类
@EnableTransactionManagement导入了TransactionManagementConfigurationSelector.class
ProxyTransactionManagementConfiguration的作用
事物概念解析
什么是事物?
事务是逻辑上的一组执行单元,要么都执行,要么都不执行
事物的特性(ACID)
ACID
是指数据库管理系统
DBMS
中事物所具有四个特性
eg:
在数据库系统中,一个事务由一系列的数据库操作组成一个完整的逻辑过程,比如银行转账,从
原账户扣除金额,目标账户增加金额
①
:atomicity
【原子性】
原子性表现为
操作不能被分割
,那么这二个操作 要么
同时完成
,要么就
全部不完成
,若事务出错了,
那么事务就会回滚,
好像什么 都 没有发生过
②
:Consistency
【一致性】
一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务开始前是一个一致状态,
事务结束后是另一个一致状态,
事务将数据库从一个一致状态转移到另一个一致状态
③
:Isolation
【隔离性】
所谓的独立性就是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个
事务修改,只要另外一个事务还未提交,它所访问的数据就不受未提交事务的影响。换句话说,一个事
务的影响在该事务提交前对其它事务是不可见的
④
:Durability
【持久性】
若事务已经提交了,那么就回在数据库中永久的保存下来
Spring事务三大接口介绍
- PlatformTransactionManager: (平台)事务管理器
- TransactionDefinition: 事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则
- TransactionStatus: 事务运行状态
PlatformTransactionManager接口介绍:
Spring
并不直接管理事务,而是提供了多种事务管理器
,他们将事务管理的职责委托给
Hibernate
或者
JTA
等持
久化机制所提供的相关平台框架的事务来实现。通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现
就是各个平台自己的事情了。
public interface PlatformTransactionManager {
/**
* 获取事物状态
*/
TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
/**
* 事物提交
*/
void commit(TransactionStatus status) throws TransactionException;
/**
* 事物回滚
*/
void rollback(TransactionStatus status) throws TransactionException;
}
TransactionDefinition 定义事物属性
TransactionDefinition
接口中定义了
5个方法以及一些表示事务属性的常量比如隔离级别、传播行为等的常量。
TransactionStatus接口介绍
TransactionStatus
接口用来记录事务的状态 该接口定义了一组方法
,用来获取或判断事务的相应状态信息。
PlatformTransactionManager.getTransaction(…)
方法返回一个
TransactionStatus 对象。返回的TransactionStatus
对象可能代表一个新的或已经存在的事务(如果在当前调用堆栈有一个符合条件的事物。
public interface TransactionStatus extends SavepointManager, Flushable {
/**
* 是否为新事物 *
*/
boolean isNewTransaction();
/**
* 是否有保存点
*/
boolean hasSavepoint();
/**
* 设置为只回滚
*/
void setRollbackOnly();
/**
* 是否为只回滚
*/
boolean isRollbackOnly();
/**
* 属性
*/
@Override
void flush();
/**
* 判断当前事物是否已经完成
*/
boolean isCompleted();
}
SpringBoot 2.4.5 事务自动装配原理
spring-boot-autoconfigure.spring.factories中已导入事务自动装配类
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
public class TransactionAutoConfiguration {
......
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(TransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
}
}
这里引入了@EnableTransactionManagement这个注解。熟悉spring的我们都知道,这个意味着开启事务管理。
@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 2147483647;
}
@EnableTransactionManagement导入了TransactionManagementConfigurationSelector.class
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
protected String[] selectImports(AdviceMode adviceMode) {
switch(adviceMode) {
case PROXY:
//默认PROXY
//往容器中添加组件 : AutoProxyRegistrar和ProxyTransactionManagementConfiguration
return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[]{this.determineTransactionAspectClass()};
default:
return null;
}
}
}
我们先来看看AutoProxyRegistrar做了什么
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@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;
}
//获取注解的mode属性
Object mode = candidate.get("mode");
//获取注解的proxyTargetClass
Object proxyTargetClass = candidate.get("proxyTargetClass");
//根据mode和proxyTargetClass的判断来注册不同的组件
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
//注册组件
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
}
}
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
分析出
AutoProxyRegistrar
会为我们容器中导入了一个叫
InfrastructureAdvisorAutoProxyCreator
的组件
我们来看下
InfrastructureAdvisorAutoProxyCreator
继承图
,
有没有一点熟悉的味道
看看几个后置处理器做了什么事情
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
ProxyTransactionManagementConfiguration的作用
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
//导入了类型为BeanFactoryTransactionAttributeSourceAdvisor 的Bean: org.springframework.transaction.config.internalTransactionAdvisor
@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;
}
}
以上分析得知事物创建代理对象最主要的是InfrastructureAdvisorAutoProxyCreator的后置处理器为我们创建代理对象,实际上是他的父类AbstractAutoProxyCreator的postProcessAfterInitialization方法
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
当前对象是否需要包装
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
创建事务代理对象流程图:
事务传播行为
spring事务的传播行为说的是,当多个事务同时存在的时候,spring如何处理这些事务的行为。
- ① PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
- ② PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
- ③ PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
- ④ PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
- ⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- ⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
- ⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按REQUIRED属性执行。
Spring中的隔离级别
- ① ISOLATION_DEFAULT:这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。
- ② ISOLATION_READ_UNCOMMITTED:读未提交,允许另外一个事务可以看到这个事务未提交的数据。
- ③ ISOLATION_READ_COMMITTED:读已提交,保证一个事务修改的数据提交后才能被另一事务读取,而且能看到该事务对已有记录的更新。
- ④ ISOLATION_REPEATABLE_READ:可重复读,保证一个事务修改的数据提交后才能被另一事务读取,但是不能看到该事务对已有记录的更新。
- ⑤ ISOLATION_SERIALIZABLE:一个事务在执行的过程中完全看不到其他事务对数据库所做的更新。
Spring事务失效的几种情况
- 数据库引擎不支持事务,入使用Mysql的MyISAM存储引擎
- 注解@Transactional所在类没有被Spring扫描,没有加@Service、@Component等注解
- 注解@Transactional所在类不是public的
- 外层方法没有加@Transactional注解:
- @Transactional propagation 属性设置错误
b方法新开了一个事务
- 异常别吃了或者回滚异常类型不一致