@EnableTransactionManagement
@Import({TransactionManagementConfigurationSelector.class}组件导入了两个组件
- AutoProxyRegistrar
- ProxyTransactionManagementConfiguration
在ProxyTransactionManagementConfiguration里面主要创建了
- BeanFactoryTransactionAttributeSourceAdvisor
- AnnotationTransactionAttributeSource
- TransactionInterceptor
TransactionInterceptor类图
事务拦截器,实现MethodInterceptor
事务增强器BeanFactoryTransactionAttributeSourceAdvisor类图
Spring 是如何管理事务的?
1. PlatformTransactionManager:事务管理器--主要用于平台相关事务的管理
主要有三个方法:
-
commit 事务提交;
-
rollback 事务回滚;
-
getTransaction 获取事务状态。
2. TransactionDefinition:事务定义信息--用来定义事务相关的属性,给事务管理器PlatformTransactionManager使用
这个接口有下面四个主要方法:
-
getIsolationLevel:获取隔离级别;
-
getPropagationBehavior:获取传播行为;
-
getTimeout:获取超时时间;
-
isReadOnly:是否只读(保存、更新、删除时属性变为false--可读写,查询时为true--只读)
事务管理器能够根据这个返回值进行优化,这些事务的配置信息,都可以通过配置文件进行配置。
3. TransactionStatus:事务具体运行状态--事务管理过程中,每个时间点事务的状态信息。
例如它的几个方法:
-
hasSavepoint():返回这个事务内部是否包含一个保存点,
-
isCompleted():返回该事务是否已完成,也就是说,是否已经提交或回滚
-
isNewTransaction():判断当前事务是否是一个新事务
声明式事务的优缺点:
-
优点:不需要在业务逻辑代码中编写事务相关代码,只需要在配置文件配置或使用注解(@Transaction),这种方式没有侵入性。
-
缺点:声明式事务的最细粒度作用于方法上,如果像代码块也有事务需求,只能变通下,将代码块变为方法。
事务实现原理
1.创建代理对象
代理对象生成入口图
@Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { //生成AOP代理对象 事务和AOP 都会生成代理对象 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } //不需要增强的 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } //是否是基础bean,是否需要跳过 //shouldSkip 事务 跳过,AOP根据条件判断是否要跳过 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. //如果有通知就创建代理对象 添加@aspect 或者实现Advice接口的 就是有通知 //getAdvicesAndAdvisorsForBean 事务增强器对象 //事务找到:BeanFactoryTransactionAttributeSourceAdvisor //得到Advisors 通知类 这里是区分aop和事务的 事务找到 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); //找到合适的通知器不为空 if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); //创建代理类 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; }