目录
一、开启事务入口类 @EnableTransactionManagement
五、工具类作用--TransactionSynchronizationManager
一、开启事务需要哪些步骤
一、开启事务入口类 @EnableTransactionManagement
这注解中的都做了那些事?
首先通过Import的方式将这个事务切面入口类TransactionManagementConfigurationSelector 变成beandefinition对象,接下来进入源码初探:
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> { /** * {@inheritDoc} * @return {@link ProxyTransactionManagementConfiguration} or * {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and * {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively */ @Override protected String[] selectImports(AdviceMode adviceMode) { switch (adviceMode) { //ProxyTransactionManagementConfiguration 切面相关的东西 case PROXY: return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()}; case ASPECTJ: return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME}; default: return null; } } }
首先进入 AutoProxyRegistrar这个类中看一下都做了那些事? 主要方法 registerBeanDefinitions
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean candidateFound = false; Set<String> annoTypes = importingClassMetadata.getAnnotationTypes(); for (String annoType : annoTypes) { AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType); if (candidate == null) { continue; } Object mode = candidate.get("mode"); Object proxyTargetClass = candidate.get("proxyTargetClass"); if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) { candidateFound = true; if (mode == AdviceMode.PROXY) { //注册AOp的入口类 InfrastructureAdvisorAutoProxyCreator 没有入口类不能生成代理 AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry); if ((Boolean) proxyTargetClass) { //把属性设置到入口类中,最终会copy到prosyFactory中 AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); return; } } } } //省略..... }
生成事务切面。切面(Advisor)中的两个核心要素,切点(PointCut)和增强(Advice),任何切面都有的,是切面中的一种规范
二、切面的生成相关逻辑:
ProxyTransactionManagementConfiguration类:
@Configuration public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration { @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() { //创建事务切面 ,切面中有创建切点 BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor(); //切面里面设置处理事务的属性对象 transactionAttributeSource()方法返回一个TransactionAttributeSource对象,这个对象呢是解析@Transaction注解的并且封装成TransactionAttribute //对象 advisor.setTransactionAttributeSource(transactionAttributeSource()); //设置切面中的advice advisor.setAdvice(transactionInterceptor()); //设置切面排序,通过@EnableTransactionManagement注解中的属性可以设置 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() { //创建事务增强 实现了 MethodInterceptor接口 TransactionInterceptor interceptor = new TransactionInterceptor(); //事务属性管理器设置到davice中 interceptor.setTransactionAttributeSource(transactionAttributeSource()); if (this.txManager != null) { //设置事务管理器 这个属性是在父类中 interceptor.setTransactionManager(this.txManager); } return interceptor; } }
三、切点PointCut
在bean实例化最后判断是否生成代理的逻辑中要进行判断matches,一个是ClassFilter,这个是默认是true,另一个是MethodMaches,这个是主要的判断逻辑,如下: 类 TransactionAttributeSourcePointcut
@Override
public boolean matches(Method method, Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
//只要方法上面能拿到实物属性就返回true,就生成代理
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
核心代码 在类AbstractFallbackTransactionAttributeSource中的getTransactionAttribute 方法:
public TransactionAttribute getTransactionAttribute(Method method, 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. //如果method不是public的返回null TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass); //省略。。。。 } }
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) { // Don't allow no-public methods as required. if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } // Ignore CGLIB subclasses - introspect the actual user class. Class<?> userClass = ClassUtils.getUserClass(targetClass); // 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 = ClassUtils.getMostSpecificMethod(method, userClass); // If we are dealing with method with generic parameters, find the original method. specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod); // 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. //如果方法上面没有@Transaction注解,则去类上看有没有改注解,这就是为什么前面classfilter直接返回true的原因。逻辑跟方法一样的 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 determineTransactionAttribute(AnnotatedElement ae) { if (ae.getAnnotations().length > 0) { for (TransactionAnnotationParser annotationParser : this.annotationParsers) { //判断方法上有没有@Transaction注解,并将注解中的属性值封装成key value形式 TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae); if (attr != null) { return attr; } } } return null; }
四、Advice 增强逻辑:
核心类TransactionInterceptor 实现了 MethodInterceptor接口,肯定会实现invoke方法,只有当代理对象去调用方法时,进入到invoke
@Override public Object invoke(final 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, new InvocationCallback() { @Override public Object proceedWithInvocation() throws Throwable { //火炬传递 return invocation.proceed(); } }); }
下面进入到事务切面中的核心代码逻辑invokeWithinTransaction
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // If the transaction attribute is null, the method is non-transactional. final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); //获取事务管理器--需要自己在代码中定义 final PlatformTransactionManager tm = determineTransactionManager(txAttr); //获取joinpoint final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); //只要是注解事务都会走下面的if 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; } //省略。。。。。 }
接着是 createTransactionIfNecessary中的核心了逻辑
protected TransactionInfo createTransactionIfNecessary( PlatformTransactionManager tm, 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 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"); } } } //开启事务信息对象,记录新老事务信息对象--修改事务运行的状态 return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }
重点方法getTransaction 再类中 AbstractPlatformTransactionManage
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
//重点看,。。DataSourceTransactionObject拿到对象,第一次进来为null
Object transaction = doGetTransaction();
// Cache debug flag to avoid repeated checks.
boolean debugEnabled = logger.isDebugEnabled();
if (definition == null) {
// Use defaults if no transaction definition given.
definition = new DefaultTransactionDefinition();
}
//第一次进来为null,所以不存在事务,判断逻辑是事务对象中有连接并且是active,则说明之前有事务
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
//如果不是第一次进来,则会走这个逻辑,重点看,
return handleExistingTransaction(definition, transaction, debugEnabled);
}
// Check definition settings for new transaction.
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
//第一次走,一般都会走这里 这三种传播属性处理方式第一次一样
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
//先挂起
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//开启事务
doBegin(transaction, definition);
//开启事务后,改变事物状态
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException ex) {
resume(null, suspendedResources);
throw ex;
}
catch (Error err) {
resume(null, suspendedResources);
throw err;
}
}
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + definition);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
DataSourceTransactionObject 对象的组成,在他的父类(JdbcTransactionObjectSupport)中有一个 ConnectionHolder属性,这个ConnectionHolder对象中包装这一个Connection连接。
接下来看一下newTransactionStatus方法的逻辑:
protected DefaultTransactionStatus newTransactionStatus( TransactionDefinition definition, Object transaction, boolean newTransaction, boolean newSynchronization, boolean debug, Object suspendedResources) { boolean actualNewSynchronization = newSynchronization && !TransactionSynchronizationManager.isSynchronizationActive(); //创建一个新的事务状态 注意这里的newTransaction 为true return new DefaultTransactionStatus( transaction, newTransaction, actualNewSynchronization, definition.isReadOnly(), debug, suspendedResources); }
开启事务的核心代码逻辑:
protected void doBegin(Object transaction, TransactionDefinition definition) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;//事务对象 Connection con = null; try { //如果事务对象中没有连接对象 if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { //事务管理器中拿dataSource对象,从dataSource对象中拿连接对象,这里可能是AbstractRoutingDataSource数据源 Connection newCon = this.dataSource.getConnection(); if (logger.isDebugEnabled()) { logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); } //把连接对象设置到事务对象中,新创建的连接对象中属性newConnectionHolder为true txObject.setConnectionHolder(new ConnectionHolder(newCon), true); } //设置有事务标识 txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); //设置是否只读连接和设置事务隔离级别 Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true); if (logger.isDebugEnabled()) { logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); } //关闭自动提交事务,提交交个spring来做 con.setAutoCommit(false); } //设置该链接的上一个隔离级别 prepareTransactionalConnection(con, definition); //把事务状态设置为true txObject.getConnectionHolder().setTransactionActive(true); //设置超时时间 int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } // 如果是一个新事物,建立数据源对象和连接对象的绑定关系,并且将该绑定关系的map设置到ThreadLocal中,结构形如 ThreadLocal<线程id,Map<数据源,连接对象>>,数据源是唯一的 if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder()); } } catch (Throwable ex) { if (txObject.isNewConnectionHolder()) { DataSourceUtils.releaseConnection(con, this.dataSource); txObject.setConnectionHolder(null, false); } throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); } }
总结doBegin方法做的操作:
- 从数据源中创建事务连接对象,并把事务连接对象设置到事务对象中。
- 根据@Transaction注解中的属性设置到连接对象中
- 关闭自动提交事务,并建立绑定关系。
五、工具类作用--TransactionSynchronizationManager
- 在业务代码中使用的,例如想看当前事务流转到什么情况了,
- 判断事务是否已经提交了、回滚了,是不是最新的状态等等(运行过程中判断),这个工具类是给开发人员使用的
六、总结:
学习Spring的事务牢记以下几点:
- Spring事务跟数据库连接对象钩挂的。
- 新建事务对象DataSourceTransactionObject中的newConnectionHolder属性为True,这个属性在事务提交和回滚时很重要