目录
1. JDK如何控制事务
2. Spring事务
(1)@EnableTransactionManagement注解
a. AutoProxyRegistrar
b. ProxyTransactionManagementConfiguration
(2)创建事务切面
(3)事务开启
a. 创建事务
b. 获取连接对象
c. 事务管理器
我们先看一段代码:
public static void main(String[] args) {
Connection connection = null;
try {
// 1.获取连接对象
connection = ConnectionUtil.getConnection();
// 2.开启事务的前奏,关闭自动提交
connection.setAutoCommit(false);
// 3.执行DML语句
insertTest1(connection);
insertTest2(connection);
// 4.事务提交
connection.commit();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
try {
// 4.事务回滚
connection.rollback();
System.out.println("JDBC Transaction rolled back successfully");
} catch (SQLException e1) {
System.out.println("JDBC Transaction rolled back fail" + e1.getMessage());
}
} finally {
if (connection != null) {
try {
selectAll(connection);
// 5.连接关闭
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
上面是JDK操作数据库、提交事务的流程,这是传统手艺,看懂了上面的代码有助于理解Spring事务。大致流程就是:
判断是否在同一个事务的标准就是多个DML是否为同一个连接对象。
Mysql的事务的提交方式默认为自动提交,如果有多个DML操作,每一个执行结束都会自动提交,所以要想多个DML操作在一个事务,必须将自动提交关闭(前提)。
首先Spring的事务也是运用了AOP的思想,对需要Spring管理事务的Bean生成了代理对象,然后通过代理对象拦截目标方法的执行,在方法前后增加了事务的功能。
我们知道,要实现AOP功能,必须有代理的入口类,那就是在类上加@EnableTransactionManagement注解,表示Spring对事务的支持,一般情况下该注解在配置类或SpringBoot的启动类上。
在Bean的初始化过程中,会经过InfrastructureAdvisorAutoProxyCreator类的初始化及后面的方法,会判断当前当前Bean对象是否和BeanFactoryTransactionAttributeSourceAdvisor匹配,匹配逻辑为判断该Bean的类上是否存在@Transactional注解,或者类中的某个方法上是否存在@Transactional注解,如果存在则表示该Bean需要进行动态代理产生一个代理对象作为Bean对象。
当该代理对象在执行某个方法时,会再次判断当前执行的方法是否和
BeanFactoryTransactionAttributeSourceAdvisor匹配,如果匹配则执行该Advisor中的
TransactionInterceptor的invoke()方法,大致流程为:
Spring中新建事务就是新建一个数据库连接,通过配置@EnableTransactionManagement注解开启事务功能。
该注解会@Import(TransactionManagementConfigurationSelector.class),TransactionManagementConfigurationSelector继承自AdciveModeImportSelector,AdciveModeImportSelector类实现了ImportSelector接口,重写了selectImports()方法:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {
/**
* 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:
// 默认是PROXY,就是在Spring容器中注册了这两个类AutoProxyRegistrar和ProxyTransactionManagementConfiguration类
// AutoProxyRegistrar作用是开启AOP代理功能
// ProxyTransactionManagementConfiguration作用是在Spring中注册了三个Bean:BeanFactoryTransactionAttributeSourceAdvisor、TransactionAttributeSource、TransactionInterceptor
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
// 表示不用动态代理激素,用ASPECTJ技术
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
在selectImports()方法中,会在Spring容器中注册两个Bean:
先看第一个类:AutoProxyRegistrar
它的作用是向Spring容器中注册InfrastructureAdvisorAutoProxyCreator类,这是事务的入口类,没有入口类无法生成代理。 而InfrastructureAdvisorAutoProxyCreator继承了AbstractAdvisorAutoProxyCreator,所以这个类的主要作用就是开启自动代理的作用,也就是一个BeanPostProcessor,会在初始化之后去寻找Advisor类型的Bean,并判断当前某个Bean是否有匹配的Advisor,是否需要利用动态代理产生一个代理对象。
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
// proxyTargetClass属性是生成代理时copyFrom(),会把该属性copy到代理工厂
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类
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
// 设置InfrastructureAdvisorAutoProxyCreator的proxyTargetClass为true
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
会进入到registerAutoProxyCreatorIfNecessary():
所属类:org.springframework.aop.config.AopConfigUtils
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 就是注册InfrastructureAdvisorAutoProxyCreator类
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
再看第二个类:ProxyTransactionManagementConfiguration
它是一个配置类,它又定义了另外三个bean:
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
// BeanFactoryTransactionAttributeSourceAdvisor就是一个实现事务功能的Advisor
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
// 创建事务切面BeanFactoryTransactionAttributeSourceAdvisor
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
// 设置切面中处理事务属性的对象(TransactionAttributeSource用来解析@Transactional注解)
advisor.setTransactionAttributeSource(transactionAttributeSource);
// 设置切面的advice,即advisor中的事务拦截器
advisor.setAdvice(transactionInterceptor);
// 切面排序
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.getNumber("order"));
}
return advisor;
}
// TransactionAttributeSource相当于解析@Transactional注解的工具类
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
// AnnotationTransactionAttributeSource(理解为注解属性资源类)中定义了一个Pointcut
// AnnotationTransactionAttributeSource用来解析@Transactional注解,将注解信息封装成RuleBasedTransactionAttribute对象返回
return new AnnotationTransactionAttributeSource();
}
// 定义事务拦截器,这个类很重要,事务的提交、回滚都会涉及到,会进入TransactionInterceptor.invoke()方法
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
// 创建事务拦截器
TransactionInterceptor interceptor = new TransactionInterceptor();
// 把事务属性解析器设置到advice中
interceptor.setTransactionAttributeSource(transactionAttributeSource);
// 把事务管理器设置到advice中
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
看一下事务切面类BeanFactoryTransactionAttributeSourceAdvisor:
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
// 定义事务切面的Pointcut
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
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;
}
}
它创建了TransactionAttributeSourcePointcut ,把TransactionAttributeSource传了进去,Pointcut必然有和ClassFilter和MethodMatcher,看一下TransactionAttributeSourcePointcut 类:
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
// TransactionAttributeSourceClassFilter判断类是否和TransactionAttributeSourcePointcut匹配,会调用到它的matches()方法
setClassFilter(new TransactionAttributeSourceClassFilter());
}
// MethodMatcher接口的matches()方法,方法级别的匹配。
// 用来判断方法是否和TransactionAttributeSourcePointcut匹配
@Override
public boolean matches(Method method, Class> targetClass) {
TransactionAttributeSource tas = getTransactionAttributeSource();
// 调用AbstractFallbackTransactionAttributeSource.getTransactionAttribute()方法
// 只要方法上面能拿到事务属性就返回true,就会生成代理
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
/**
* Obtain the underlying TransactionAttributeSource (may be {@code null}).
* To be implemented by subclasses.
*/
@Nullable
protected abstract TransactionAttributeSource getTransactionAttributeSource();
/**
* {@link ClassFilter} that delegates to {@link TransactionAttributeSource#isCandidateClass}
* for filtering classes whose methods are not worth searching to begin with.
*/
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class> clazz) {
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
TransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
// 看匹配方法org.springframework.transaction.annotation.AnnotationTransactionAttributeSource.isCandidateClass()
return (tas == null || tas.isCandidateClass(clazz));
}
}
}
它继承自StaticMethodMatcherPointcut,该类又继承StaticMethodMatcher、并实现了Pointcut接口,StaticMethodMatcher实现了MethodMatcher接口。
理论上@Transactional注解也可以加在类上,但日常工作中很少这么使用,虽然引入了TransactionAttributeSourceClassFilter内部类,但是对类上的匹配却是不痛不痒,直接返回了true,最终会调到这里:
所属类:org.springframework.core.annotation.AnnotationUtils
public static boolean isCandidateClass(Class> clazz, String annotationName) {
if (annotationName.startsWith("java.")) {
return true;
}
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
return false;
}
return true;
}
真正的匹配是在方法级别,就是matches(),这是MethodMatcher接口的方法,只要方法上面能拿到事务属性就返回true,就会生成代理,调用TransactionAttributeSource.getTransactionAttribute()方法:
所属类springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
// 检查缓存,缓存里面保存的当前类和方法是否存在@Transactional注解
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute 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 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.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
进入computeTransactionAttribute()获取方法上的@Transactional注解信息:
所属类:transaction.interceptor.AbstractFallbackTransactionAttributeSource
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class> targetClass) {
// Don't allow no-public methods as required.
// 如果是非public方法,则返回null,不会生成代理
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.
// 检查方法上是否存在@Transactional注解,获取方法上面的@Transactional注解信息
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// Second try is the transaction attribute on the target class.
// 如果方法上没有@Transactional注解,再检查类上是否有
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()方法获取注解信息:
所属类:org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
进入本类的determineTransactionAttribute():
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
// 解析注解信息,SpringTransactionAnnotationParser.parseTransactionAnnotation()方法
TransactionAttribute attr = parser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
进入SpringTransactionAnnotationParser.parseTransactionAnnotation(),这个类是用来解析@Transactional注解的解析器。
所属类:org.springframework.transaction.annotation.SpringTransactionAnnotationParser
// 获取注解信息
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 获取方法上面的注解属性
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
// 解析@Transactional注解中的属性,并封装成对象
return parseTransactionAnnotation(attributes);
} else {
return null;
}
}
进入本类的parseTransactionAnnotation():
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
// 解析@Transactional注解信息封装成RuleBasedTransactionAttribute对象
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 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;
}
最终把注解属性封装成RuleBasedTransactionAttribute对象,如果没有@Transactional注解的方法,则会去解析类上面的@Transactional注解属性,原理和解析方法上的注解类似,流程就是先找方法,再找类。
接下来看代理逻辑:
TransactionInterceptor就是事务的拦截器类,继承自TransactionAspectSupport类,并实现了MethodInterceptor接口。
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
public TransactionInterceptor(TransactionManager ptm, TransactionAttributeSource tas) {
setTransactionManager(ptm);
setTransactionAttributeSource(tas);
}
@Deprecated
public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
setTransactionManager(ptm);
setTransactionAttributeSource(tas);
}
@Deprecated
public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
setTransactionManager(ptm);
setTransactionAttributes(attributes);
}
当某个类中存在@Transactional注解时,到时就产生一个代理对象作为Bean,代理对象在执行某个方法时,最终就会进入到TransactionInterceptor的invoke()方法。
看TransactionInterceptor的invoke()方法:
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...
// 执行后续的Interceptor,及代理的方法invocation::proceed
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
当用代理对象调用的时候,就会进入invokeWithinTransaction()方法:
所属类:org.springframework.transaction.interceptor.TransactionAspectSupport
protected Object invokeWithinTransaction(Method method, @Nullable Class> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
// 获取事务属性源对象,TransactionAttribute类相当于@Transactional注解信息的一个封装类
TransactionAttributeSource tas = getTransactionAttributeSource();
// 通过源对象获取@Transactional注解中的配置信息
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 获取Spring容器中定义的TransactionManager事务管理器对象
final TransactionManager tm = determineTransactionManager(txAttr);
// ReactiveTransactionSupportManager用的少,它执行方式是响应式的,原理流程和普通的是一样的
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
throw new TransactionUsageException(
"Unsupported annotated transaction on suspending function detected: " + method +
". Use TransactionalOperator.transactional extensions instead.");
}
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
if (adapter == null) {
throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
method.getReturnType());
}
return new ReactiveTransactionSupport(adapter);
});
return txSupport.invokeWithinTransaction(
method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
}
// 把tm强制转换为PlatformTransactionManager,所以我们在定义时须定义为PlatformTransactionManager类型
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
// 获取joinpoint,joinpoint的唯一标识,就是当前执行的方法名称(标注了@Transactionl的方法名)
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 处理声明式事务
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
// 开启事务
// TransactionInfo表示一个逻辑事务,比如两个逻辑事务属于同一个物理事务(重要程度:5)
TransactionInfo txInfo = createTransactionIfNecessary(ptm, 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.
// 火炬传递,调用被代理对象中的被代理方法(原始方法)
// 执行TransactionInterceptor.invoke()最后一行匿名对象方法invocation::proceed
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
// 回滚事务
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 清空线程中的transactionInfo
cleanupTransactionInfo(txInfo);
}
if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
// 提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
// 编程式事务
else {
Object result;
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
try {
Object retVal = invocation.proceedWithInvocation();
if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
return retVal;
}
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);
}
});
}
在容器启动的时候,就会把AnnotationTransactionAttributeSource类设置到transactionAttributeSource属性中,所以上面方法中的代码:
TransactionAttributeSource tas = getTransactionAttributeSource()
就可以拿到属性解析对象,接着再获取事务管理器:
protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
// Do not attempt to lookup tx manager if no tx attributes are set
if (txAttr == null || this.beanFactory == null) {
return getTransactionManager();
}
String qualifier = txAttr.getQualifier();
if (StringUtils.hasText(qualifier)) {
return determineQualifiedTransactionManager(this.beanFactory, qualifier);
}
else if (StringUtils.hasText(this.transactionManagerBeanName)) {
return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
}
else {
// 从advice中获取事务管理器
TransactionManager defaultTransactionManager = getTransactionManager();
if (defaultTransactionManager == null) {
defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
if (defaultTransactionManager == null) {
// 从Spring容器获取事务管理器,获取实现TransactionManager接口的实例
defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
this.transactionManagerCache.putIfAbsent(
DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
}
}
return defaultTransactionManager;
}
}
所以,可以自定义事务管理器,PlatformTransactionManager实现TransactionManager接口,一般就是采用这种方式:
@Bean
public PlatformTransactionManager annotationDrivenTransactionManager(DataSource dataSource) {
DataSourceTransactionManager dtm = new DataSourceTransactionManager();
dtm.setDataSource(dataSource);
return dtm;
}
接下来进入开启(创建)事务的核心方法createTransactionIfNecessary():
所属类:org.springframework.transaction.interceptor.TransactionAspectSupport
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// If no name specified, apply method identification as transaction name.
// 把方法名作为一个事务名称
if (txAttr != null && txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
}
};
}
// 每个逻辑事务都会创建一个TransactionStatus,但是TransactionStatus中有一个属性代表当前逻辑事务底层的物理事务不是最新的
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
// 开启事务*****
status = tm.getTransaction(txAttr);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
"] because no transaction manager has been configured");
}
}
}
// 把事务状态和事务属性等信息封装成一个TransactionInfo对象,表示得到了一个事务,可能是新创建的事务,也可能是拿到已有的
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
进入tm.getTransaction(txAttr)开启事务方法:
所属类:org.springframework.transaction.support.AbstractPlatformTransactionManager
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// Use defaults if no transaction definition given.
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 得到一个DataSourcetranctionObject类(就是事务对象)****
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
// 判断之前是否已存在事务对象(第一次进来为空)
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
// 如果不是第一次进来, 则走这里,表示之前已开启事务,则为现有事务创建TransactionStatus。
return handleExistingTransaction(def, transaction, debugEnabled);
}
// Check definition settings for new transaction.
// 检查事务设置的超时时间
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// 下面处理事务的传播机制
// No existing transaction found -> check propagation behavior to find out how to proceed.
// 若事务属性式为PROPAGATION_MANDATORY,表示必须运行在事务中,没有就抛出异常
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
/**
* 如果存在事务,以下三种传播机制都会进入相同的处理逻辑
* PROPAGATION_REQUIRED:存在事务就加入到当前的事务,没有就新开一个
* PROPAGATION_REQUIRES_NEW:新开一个事务,若当前存在事务就挂起当前事务
* PROPAGATION_NESTED: 表示如果当前正有一个事务在运行中,则该方法应该运行在一个嵌套的事务中,
* 被嵌套的事务可以独立于封装事务进行提交或者回滚(保存点),如果封装事务不存在,行为就像PROPAGATION_REQUIRES_NEW
*/
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 没有事务需要挂起,不过TransactionSynchronization有可能需要挂起
// SuspendedResources表示当前线程被挂起的资源持有对象(数据库连接、TransactionSynchronization)
/**
* 挂起当前事务,SuspendedResources表示当前线程被挂起的资源持有对象(数据库连接、TransactionSynchronization)
* 逻辑走到这里,经过了上面的isExistingTransaction(transaction)可以断定当前不存在事务,所有这里挂起当前事务传递一个null进去
*/
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
// 开启新事务,事务中就会有数据库连接了,并且isTransactionActive为true
// 新创建一个事务状态TransactionStatus对象,该对象保存了很多信息,包括被挂起的资源(重要程度:5)
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// 创建一个空的事务
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + def);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
}
先看doGetTransaction(),获取数据源事务对象,会去ThreadLocal中拿连接对象:
所属类:org.springframework.jdbc.datasource.DataSourceTransactionManager
protected Object doGetTransaction() {
// 创建一个事务对象
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
// 根据DataSource对象去ThreadLocal中拿连接对象ConnectionHolder,第一次进来拿的时候是空的
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
DataSourceTransactionObject封装了与连接对象相关的属性,如是否只读、隔离级别、是否按回滚点进行回滚。
ConnectionHolder是DataSourceTransactionObject父类JdbcTransactionObjectSupport的属性,是数据库连接的封装类。会从TransactionSynchronizationManager(数据源管理器)中拿到连接对象:
public static Object getResource(Object key) {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Object value = doGetResource(actualKey);
if (value != null && logger.isTraceEnabled()) {
logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
Thread.currentThread().getName() + "]");
}
return value;
}
进入doGetResource(),从数据源管理器中获取数据源对象,也就是连接池对象:
所属类:org.springframework.transaction.support.TransactionSynchronizationManager
private static Object doGetResource(Object actualKey) {
// resources是ThreadLocal包装的Map,用来缓存资源的,比如缓存当前线程中由某个DataSource所创建的数据库连接
Map
连接对象是从ThreadLocal中获取的:
// key为DataSource对象,value为ConnectionHolder对象
private static final ThreadLocal
dataSource是从哪来的,就是启动的时候设置进去的:
@Bean
public PlatformTransactionManager annotationDrivenTransactionManager() {
DataSourceTransactionManager dtm = new DataSourceTransactionManager();
// 就是这里,把DataSource传进去
dtm.setDataSource(dataSource());
return dtm;
}
DataSource就是自定义配置的:
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://192.168.1.200:3306/test?useUnicode=true&useSSL=false");
dataSource.setUsername("root");
dataSource.setPassword("huanbao");
return dataSource;
}
对于事务管理器,补充一点,前面提到的事务配置类ProxyTransactionManagementConfiguration.transactionInterceptor()方法中的事务管理器this.txManager哪来的?
ProxyTransactionManagementConfiguration配置类继承自AbstractTransactionManagementConfiguration类,是父类中定义的。
@Configuration
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
@Nullable
protected AnnotationAttributes enableTx;
/**
* Default transaction manager, as configured through a {@link TransactionManagementConfigurer}.
*/
@Nullable
protected TransactionManager txManager;
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableTx = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
if (this.enableTx == null) {
throw new IllegalArgumentException(
"@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
}
}
// 支持自定义,依赖注入
@Autowired(required = false)
void setConfigurers(Collection configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
if (configurers.size() > 1) {
throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
}
// 拿到参数中传进来的某一个
TransactionManagementConfigurer configurer = configurers.iterator().next();
// 就可以获取到自定义的事务管理器
this.txManager = configurer.annotationDrivenTransactionManager();
}
支持自定义事务管理器,如:
@Component
public class TransactionManagementConfigurerBean implements TransactionManagementConfigurer {
@Autowired
private DataSource dataSource;
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
DataSourceTransactionManager dtm = new DataSourceTransactionManager();
dtm.setDataSource(dataSource);
return dtm;
}
}
到此,事务已经创建好了,接下来就是事务提交、回滚和传播属性的相关内容。
由于内容较多,为了方便阅读,分成了三个章节,欢迎进入~~