利用 Spring 框架可以很容易的使用注解的方式来使用事务,为我们的开发带来了巨大的便利,这种便利的实现是通过 Spring 本身的一系列机制来实现的,主要包含动态代理和 Spring Bean 的加载过程。本文将深入源码,揭开层层面纱…
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) public void methodInTransaction() { // 对数据库的一些操作 }
我们只需要在对应的方法上使用 @Transactional
注解即可让这个方法在事务中执行。这里需要注意的是,如果是在一个类中的两个方法,事务是不会生效的。举例:
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** * Created by zhangbo on 2019-02-28. */ public class TransactionTest { public void methodNotIntransaction() { this.methodInTransaction(); // 此时被调用的方法 methodInTransaction 的事务并不会生效 } @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) public void methodInTransaction() { // 对数据库的一些操作 } }
为何不会生效?是因为这样的调用不会经过 Spring 的代理,无法通过 Spring 的 advisor 来拦截数据库操作请求。
首先我们来了解一下 Spring Bean 的生命周期
作者:土豆肉丝盖浇饭
链接: https://www.jianshu.com/p/6d5c58168493
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
通过上面的流程我们可以看到,BeanPostProcessor 中的两个方法 postProcessBeforeInitialization
和 postProcessAfterInitialization
分别在 bean 调用 init 方法前后调用。其中对于对象的代理就是在 postProcessAfterInitialization
方法中完成的,用代理的 bean 来替换原来的 bean
默认情况下, BeanPostProcessor
的职能是通过默认实现类 DefaultAdvisorAutoProxyCreator
实现的,类 DefaultAdvisorAutoProxyCreator
继承自 AbstractAdvisorAutoProxyCreator
该类的继承关系如下图
DefaultAdvisorAutoProxyCreator
如何代理被 @Transactional
注解的方法所属类 来看看 AbstractAutoProxyCreator
中发生了什么
/** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */ // 类 AbstractAutoProxyCreator @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); // 主要逻辑在这里 } } return bean; }
跟进 wrapIfNecessary
方法
/** * Wrap the given bean if necessary, i.e. if it is eligible for being proxied. * @param bean the raw bean instance * @param beanName the name of the bean * @param cacheKey the cache key for metadata access * @return a proxy wrapping the bean, or the raw bean instance as-is */ // 类 AbstractAutoProxyCreator 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 从而创建代理类 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); 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; }
// AbstractAdvisorAutoProxyCreator 类 @Override @Nullable protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); }
/** * Find all eligible Advisors for auto-proxying this class. * @param beanClass the clazz to find advisors for * @param beanName the name of the currently proxied bean * @return the empty List, not {@code null}, * if there are no pointcuts or interceptors * @see #findCandidateAdvisors * @see #sortAdvisors * @see #extendAdvisors */ // AbstractAdvisorAutoProxyCreator 类 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 获取 候选 advisor // BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false); List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 筛选 可用的 advisor List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // 此处会获取名称为org.springframework.transaction.interceptor.TransactionInterceptor#0的拦截器 extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
我们来看看生成的动态类是什么样子的?
其中有一个 advisor 为
adviceBeanName:org.springframework.transaction.interceptor.TransactionInterceptor#0
我们此时来看看 org.springframework.transaction.interceptor.TransactionInterceptor
里究竟是如何执行 SQL 语句的。我们需要关注的方法为 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
方法
// TransactionAspectSupport.java 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); final String joinpointIdentification = methodIdentification(method, targetClass); // txAttr(事务属性)为空或者tm(事务管理器)为空时,是声明式事务 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 { // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in. try { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, new TransactionCallback<Object>() { @Override public Object doInTransaction(TransactionStatus 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. return new ThrowableHolder(ex); } } finally { cleanupTransactionInfo(txInfo); } } }); // Check result: It might indicate a Throwable to rethrow. if (result instanceof ThrowableHolder) { throw ((ThrowableHolder) result).getThrowable(); } else { return result; } } catch (ThrowableHolderException ex) { throw ex.getCause(); } } }
至此,我们基本了解了 Spring 声明式事务的工作流程