Spring:事务处理的实现

事务处理的实现

Spring在对事务进行统一处理其实底层还是使用到了aopTransactionProxyFactoryBean将对事务的处理事件使用aop做增强和织入。对数据源的事务处理(提交、回滚)的实现是通过事务管理器TransactionManager来进行支持的。通过TransactionAspectSupport来赋予TransactionManager的事务处理可以通过aop进行操作。

事务架构

事务处理拦截器的配置

事务处理拦截器是对target的方法进行拦截,然后调用TransactionManager对方法的事务进行管理。

事务处理拦截器是在TransactionProxyFactoryBean的父类AbstractSingletonProxyFactoryBean中进行配置的。在bean的生命周期中,在处理init-method的方法中,先调用后置处理器的before,然后如果是InitializingBean类型的bean还会执行afterPropertiesSet方法,然后才会依次执行init-method和后置处理器的after方法。

afterPropertiesSet方法

// AbstractSingletonProxyFactoryBean#afterPropertiesSet
	public void afterPropertiesSet() {
   
        // <1> 对target的;类型进行检查,必须是一个bean reference
		if (this.target == null) {
   
			throw new IllegalArgumentException("Property 'target' is required");
		}
		if (this.target instanceof String) {
   
			throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value");
		}
		if (this.proxyClassLoader == null) {
   
			this.proxyClassLoader = ClassUtils.getDefaultClassLoader();
		}
		// 创建一个ProxyFactory,和aop中的ProxyFactoryBean功能很相近,
        // 能够操作拦截器和创建代理对象
		ProxyFactory proxyFactory = new ProxyFactory();
		// <2> 将拦截器包装成为advisor,通过aop知道ProxyFactory可以管理advisor,进而操作通知器链等
        // 首先是preInterceptors 然后加入TransactionInterceptor的advisor 最后postInterceptors
		if (this.preInterceptors != null) {
   
			for (Object interceptor : this.preInterceptors) {
   
				proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
			}
		}

		// Add the main interceptor (typically an Advisor).
        // <3> 这是对TransactionInterceptor创建对应的advisor
		proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));

		if (this.postInterceptors != null) {
   
			for (Object interceptor : this.postInterceptors) {
   
				proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
			}
		}
		// 对proxyFactory进行一些设置,在使用proxyFactory创建代理对象的时候需要
		proxyFactory.copyFrom(this);

		TargetSource targetSource = createTargetSource(this.target);
		proxyFactory.setTargetSource(targetSource);

		if (this.proxyInterfaces != null) {
   
			proxyFactory.setInterfaces(this.proxyInterfaces);
		}
		else if (!isProxyTargetClass()) {
   
			// Rely on AOP infrastructure to tell us what interfaces to proxy.
			Class<?> targetClass = targetSource.getTargetClass();
			if (targetClass != null) {
   
				proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
			}
		}

		postProcessProxyFactory(proxyFactory);
		// <4> 创建代理对象,过程和aop中的一样(拦截器链在这个方法中已经构建好了)
		this.proxy = proxyFactory.getProxy(this.proxyClassLoader);
	}

<3>中的wrapaop中的方法是一样的。重点在于createMainInterceptor方法做了什么。Interceptor需要有AdvicePointcut

如果已经存在pointcut就是使用DefaultPointcutAdvisor,否则就创建TransactionAttributeSourceAdvisor

	private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
	
	protected Object createMainInterceptor() {
   
        // 做一些检查
		this.transactionInterceptor.afterPropertiesSet();
		if (this.pointcut != null) {
   
			return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);
		}
		else {
   
			// Rely on default pointcut.
			return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);
		}
	}

事务处理配置的读入

TransactionAttributeSourceAdvisor类

这是在事务处理中比较常用的通知器。通知器需要有AdvicePointcut,它是如何配置的。Advice其实就是TransactionInterceptorPointcut其实就是TransactionAttributeSourcePointcut,可以从对事务的配置属性中读取信息。

	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
   
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
   
			return (transactionInterceptor != null ? transactionInterceptor.getTransactionAttributeSource() : null);
		}
	};

TransactionAttributeSourcePointcut类

在这个类中就实现了对拦截方法的检查,是否能够拦截该事务。

使用TransactionAttributeSource,根据方法名判断是否有匹配的TransactionAttribute如果有那么就可以拦截。而TransactionAttributeSource通过TransactionInterceptor获得。TransactionAttributeSource属性是TransactionInterceptor在注入依赖的时候配置好的。

	public boolean matches(Method method, Class<?> targetClass) {
   
		TransactionAttributeSource tas = getTransactionAttributeSource();
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}

// TransactionAspectSupport#setTransactionAttributes
	public void setTransactionAttributes(Properties transactionAttributes) {
   
		NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
		tas.setProperties(transactionAttributes);
		this.transactionAttributeSource = tas;
	}
// NameMatchTransactionAttributeSource#getTransactionAttribute
	/** Keys are method names; values are TransactionAttributes. */
	private Map<String, TransactionAttribute> nameMap = new HashMap<>();
	public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
   
		if (!ClassUtils.isUserLevelMethod(method)) {
   
			return null;
		}

		// Look for direct name match.
		String methodName = method.getName();
		TransactionAttribute attr = this.nameMap.get(methodName);

		if (attr == null) {
   
			// Look for most specific name match.
			String bestNameMatch = null;
			for (String mappedName : this.nameMap.keySet()) {
   
				if (isMatch(methodName, mappedName) &&
						(bestNameMatch == null || bestNameMatch.length() <= mappedName.length())) {
   
					attr = this.nameMap.get(mappedName);
					bestNameMatch = mappedName;
				}
			}
		}

		return attr;
	}

事务处理器拦截器的作用

TransactionProxyFactoryBeangetObject方法获取代理对象。

// AbstractSingletonProxyFactoryBean#getObject
	public Object getObject() {
   
		if (this.proxy == null) {
   
			throw new FactoryBeanNotInitializedException();
		}
		return this.proxy;
	}

proxy就是在执行afterPropertiesSet方法时进行设置的。和aop一样是通过DefaultAopProxyFactorycreateAopProxy方法创建。所以在执行通知器链的时候对target的代理实现原理也是一样的。具体的不同就是多了专门用来处理事务的拦截器TransactionInterceptor

在遍历MethodInterceptor的时候会执行invoke方法。那么TransactionInterceptorinvoke就是对target的方法能够进行事务处理的地方,所以在invoke方法中会使用到TransactionManager

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);

		// <1> Adapt to TransactionAspectSupport's invokeWithinTransaction...
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

<1>最后是使用lambda表达式创建了一个InvocationCallback对象,当调用InvocationCallback#proceedWithInvocation的时候会调用ReflectiveMethodInvocation#proceed

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 TransactionManager tm = determineTransactionManager(txAttr);
		// <1> 有关于reactive响应式的事务管理器
		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.getAdapt
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值