1,spring 事务的简单概述
由于实现事务功能的方式各不相同, Spring 进行了统一的抽象, 形成了 PlatformTransactionManager 事务管理器顶级接口(平台事务管理器), 事务的提交, 回滚等操作全部交给它来实现
先来看下三大接口
PlatformTransactionManager : 事务管理器
TransactionDefinition : 事务的一些基础信息, 如超时时间, 隔离级别, 传播属性等
TransactionStatus : 事务的一些状态信息, 如是否是一个新的事务, 是否已被标记为回滚
2,PlatformTransactionManager
相关类方法:
- public interface PlatformTransactionManager {
- // 获取事务状态
- TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
- // 事务提交
- void commit(TransactionStatus status) throws TransactionException;
- // 事务回滚
- void rollback(TransactionStatus status) throws TransactionException;
}
继承关系:
- PlatformTransactionManager
- AbstractPlatformTransactionManager
- DataSourceTransactionManager(重点)
- HibernateTransactionManager
JpaTransactionManager
触发不同的事物管理器
springboot 对 PlatformTransactionManager 的默认配置实现(引用 spring-boot-starter-web 中 jdbc 相关 jar)
- public class DataSourceTransactionManagerAutoConfiguration {
- @Configuration
- @ConditionalOnSingleCandidate(DataSource.class)
- static class DataSourceTransactionManagerConfiguration {
- private final DataSource dataSource;
- private final TransactionManagerCustomizers transactionManagerCustomizers;
- DataSourceTransactionManagerConfiguration(DataSource dataSource,
- ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
- this.dataSource = dataSource;
- this.transactionManagerCustomizers = transactionManagerCustomizers
- .getIfAvailable();
- }
- @Bean
- @ConditionalOnMissingBean(PlatformTransactionManager.class)
- public DataSourceTransactionManager transactionManager(
- DataSourceProperties properties) {
- DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(
- this.dataSource);
- if (this.transactionManagerCustomizers != null) {
- this.transactionManagerCustomizers.customize(transactionManager);
- }
- return transactionManager;
- }
- }
}
通过 @ConditionalOnMissingBean(PlatformTransactionManager.class)这个注解可以直到如果没有手动配置
PlatformTransactionManager 即使用默认的子类 DataSourceTransactionManager 来管理实务
3, 事务传播特性和隔离级别
public interface TransactionDefinition {
事务传播特性:
1, 支持事务, 如果当前线程没有事务, 新建一个事务
int PROPAGATION_REQUIRED = 0;
2, 支持事务, 如果当前线程没有事务, 则以非事务执行
int PROPAGATION_SUPPORTS = 1;
3, 当前如果有事务, Spring 就会使用该事务; 否则会抛出异常
int PROPAGATION_MANDATORY = 2;
4, 如果当前线程存在事务, 或者不存在事务, 都会新建一个事务, 并且新建事务与当前事务是相互隔离的, 如果新建事务执行时, 会先将当前事务挂起, 等新建事务执行完成后, 再将放行当前事务, 如果新事物出现异常, 会正常回滚, 但不会影响当前事务
int PROPAGATION_REQUIRES_NEW = 3;
5, 不支持事务, 如果存在事务, 则会将当前事务挂起, 以非事务执行
int PROPAGATION_NOT_SUPPORTED = 4;
6, 不支持事务, 如果当前线程存在事务, 将会抛异常
int PROPAGATION_NEVER = 5;
7, 如果当前线程存在事务, 则新建一个回滚点, 如果出现异常, 则会回滚到上一个回滚点, 对于当前事务是不受任何影响的.
- int PROPAGATION_NESTED = 6;
- // 隔离级别: 默认的隔离级别(对 MySQL 数据库来说就是 ISOLATION_ READ_COMMITTED, 可以重复读)
- int ISOLATION_DEFAULT = -1;
- // 隔离级别: 读未提交
- int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
- // 隔离级别: 读已提交
- int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
- // 隔离级别: 可重复读
- int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
- // 隔离级别: 序列化
- int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
- int TIMEOUT_DEFAULT = -1;
- int getPropagationBehavior();
- int getIsolationLevel();
- int getTimeout();
- boolean isReadOnly();
- @Nullable
- String getName();
- }
4, 为什么说 spring 事务是 aop 的一种实现
finishBeanFactoryInitialization(beanFactory); 一路向后 debug 最后可以看到下面的代码
- 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;
- }
- if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
- this.advisedBeans.put(cacheKey, Boolean.FALSE);
- return bean;
- }
- // Create proxy if we have advice.
- // 这里就是获取需要代理的类 (如果存在 advice)
- // 获取 bean 对应的 advice 集合.
- Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
- if (specificInterceptors != DO_NOT_PROXY) {
- this.advisedBeans.put(cacheKey, Boolean.TRUE);
- // 将获取到的 advice 集合保存到代理对象中并返回.
- 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;
}
这里是创建代理的方法
- protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
- @Nullable Object[] specificInterceptors, TargetSource targetSource) {
- if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
- AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
- }
- ProxyFactory proxyFactory = new ProxyFactory();
- proxyFactory.copyFrom(this);
- if (!proxyFactory.isProxyTargetClass()) {
- if (shouldProxyTargetClass(beanClass, beanName)) {
- proxyFactory.setProxyTargetClass(true);
- }
- else {
- evaluateProxyInterfaces(beanClass, proxyFactory);
- }
- }
- // 将 advice 封装到 advisors 中
- Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
- proxyFactory.addAdvisors(advisors);
- // 这里的 targetSource 就是目标对象, 在后面调用的时候会用到
- proxyFactory.setTargetSource(targetSource);
- customizeProxyFactory(proxyFactory);
- proxyFactory.setFrozen(this.freezeProxy);
- if (advisorsPreFiltered()) {
- proxyFactory.setPreFiltered(true);
- }
- return proxyFactory.getProxy(getProxyClassLoader());
- }
specificInterceptors 是拦截器(如果是 aop 则是前置后置这些过滤器, 如果是事务, 则是事务拦截器)
BeanFactoryCacheOperationSourceAdvisor(保存了增强的信息)切面记录是前置, 后置等增强拦截器链而事务相关记录的是事务拦截器 private final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<>(1024); 保存方法对应的事务信息 private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256); 保存这个 bean 是否为增强 beanif (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean;}判断这个 bean 是否为代理类, 如果不是直接返回单例和多例的区别:
protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); }}将获取到的 bean 保存到 singletonObjects 中 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); 在每次调用的时候, 直接从 singletonObjects 这个 ConcurrentHashMap 中获取即可. 如果是 Prototype 在从走一遍单例的流程 else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}
5, 事务方法调用
和 aop 调用一样, 最后会调用 TransactionInterceptor 的 invock 方法
- 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 方法
- protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
- final InvocationCallback invocation) throws Throwable {
- // If the transaction attribute is null, the method is non-transactional.
- TransactionAttributeSource tas = getTransactionAttributeSource();
- final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
- 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 = null;
- try {
- // This is an around advice: Invoke the next interceptor in the chain.
- // This will normally result in a target object being invoked.
- retVal = invocation.proceedWithInvocation();
- }
- catch (Throwable ex) {
- // target invocation exception
- completeTransactionAfterThrowing(txInfo, ex);
- throw ex;
- }
- finally {
- cleanupTransactionInfo(txInfo);
- }
- 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;
- }
- }
}
来源: https://juejin.im/post/5c00a2366fb9a049c84f2df1