Spring注解式事务解析

Spring注解式事务解析


  1. 增加一个Advisor
    首先往Spring容器新增一个Advisor,BeanFactoryTransactionAttributeSourceAdvisor,它包含了TransactionInterceptor通知和TransactionAttributeSourcePointcut切点。TransactionAttributeSourcePointcut切点实际匹配使用了AnnotationTransactionAttributeSource这个类,它的作用是方法的切点匹配,解析Transactional注解,它尝试从当前类的方法,当前类,父接口方法,父接口查找Transactional注解,有则匹配到。

  2. AOP动态代理
    当普通bean实例化的时候,Spring通过AbstractAdvisorAutoProxyCreator的其中一个子类进行postProcessAfterInitialization进行AOP这个bean,织入匹配的Advisor,并生成动态代理。动态代理有2种,JdkDynamicAopProxy和ObjenesisCglibAopProxy。

  3. 拦截过程
    方法调用的时候,拿JdkDynamicAopProxy动态代理来讲,被动态代理的bean的公有方法调用会走invoke方法拦截,首先确定当前方法的拦截器链。

    			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    

    如果上面的chain为空,不走拦截,否则走拦截责任链

    				invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    				retVal = invocation.proceed();
    
  4. TransactionInterceptor事务拦截器
    内部拿到我们的TransactionInterceptor进行方法调用

    @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();
    			}
    		});
    	}
    
5.创建TransactionInfo对象
    他会先获取TransactionAttribute和PlatformTransactionManager,然后调用
    ```
    			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
    ```
    内部逻辑为拿DataSourceTransactionManager举例,
    尝试从ThreadLocal获取ConnectionHolder(包含了一个Connection)
    ```
    protected Object doGetTransaction() {
    		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
    		txObject.setSavepointAllowed(isNestedTransactionAllowed());
    		ConnectionHolder conHolder =
    				(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
    		txObject.setConnectionHolder(conHolder, false);
    		return txObject;
    	}
    ```
    然后判断是不是新事务
    ```
    	if (isExistingTransaction(transaction)) {
    			// Existing transaction found -> check propagation behavior to find out how to behave.
    			return handleExistingTransaction(definition, transaction, debugEnabled);
    		}
    ```
    不是新事务,走handleExistingTransaction逻辑,内部会根据我们配置的传递规则做不同的处理,默认的Propagation.REQUIRED就会返回TransactionStatus对象标志为已存在的事务。
    是新事务则返回TransactionStatus对象标志为新事务,代码如下:
    ```
    	boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
    				DefaultTransactionStatus status = newTransactionStatus(
    						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
    				doBegin(transaction, definition);
    				prepareSynchronization(status, definition);
    				return status;
    ```
    doBegin方法会从dataSource获取一个新连接,并设置到DataSourceTransactionObject的ConnectionHolder字段里,并且设置synchronizedWithTransaction和transactionActive为true代表新事务,然后设置con.setAutoCommit(false),最后设置ThreadLocal值,为当前ConnectionHolder。
    ```
    if (txObject.isNewConnectionHolder()) {
    				TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
    			}
    ```	
6.责任链调用下一个拦截器 
    获取了当前的TransactionInfo开始走下一个拦截器
    ```
    	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;
    			}
    ```
7.提交或回滚
    处理完了之后如果抛异常根据匹配规则是否需要回滚,默认对RuntimeException和Error回滚。如果正常返回则调用commitTransactionAfterReturning方法
    ```
    protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
    		if (txInfo != null && txInfo.hasTransaction()) {
    			if (logger.isTraceEnabled()) {
    				logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
    			}
    			txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
    		}
    	}
    ```
    进行commit,最后调用doCleanupAfterCompletion方法,清空ThreadLocal,设置con.setAutoCommit(true),并关闭连接。
原文地址:https://www.cnblogs.com/yaojf/p/7423361.html