内容简介:利用 Spring 框架可以很容易的使用注解的方式来使用事务,为我们的开发带来了巨大的便利,这种便利的实现是通过 Spring 本身的一系列机制来实现的,主要包含动态代理和 Spring Bean 的加载过程。本文将深入源码,揭开层层面纱…我们只需要在对应的方法上使用为何不会生效?是因为这样的调用不会经过 Spring 的代理,无法通过 Spring 的 advisor 来拦截数据库操作请求。
利用 Spring 框架可以很容易的使用注解的方式来使用事务,为我们的开发带来了巨大的便利,这种便利的实现是通过 Spring 本身的一系列机制来实现的,主要包含动态代理和 Spring Bean 的加载过程。本文将深入源码,揭开层层面纱…
Spring @Transactional 的使用
@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 BeanPostProcessor
首先我们来了解一下 Spring Bean 的生命周期
- 调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
- bean实例化
- 调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation(Object bean, String beanName)
- 调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
- bean注入properties
- 分别调用BeanNameAware,BeanClassLoaderAware,BeanFactoryAware中的方法
- 调用BeanPostProcessor的postProcessBeforeInitialization(Object bean, String beanName)
- 调用InitializingBean的afterPropertiesSet方法
- 调用自定义初始化方法
- 调用BeanPostProcessor的postProcessAfterInitialization(Object bean, String beanName)
- 调用DisposableBean的destroy()方法
- 调用自定义销毁方法
作者:土豆肉丝盖浇饭
链接: 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
TransactionInterceptor 类
我们此时来看看 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 声明式事务的工作流程
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- java反射原理, 注解原理
- 注解的原理又是怎么一回事
- Spring源码分析:@Autowired注解原理分析
- 【Spring】Autowired原理及与Resource注解区别
- spring-AOP(二)实现原理之AspectJ注解方式
- Spring 中异步注解 @Async 的使用、原理及使用时可能导致的问题
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
NoSQL精粹
[美]Pramod J. Sadalage、[美]Martin Fowler / 爱飞翔 / 机械工业出版社 / 2013-8 / 49.00元
《NoSQL精粹》为考虑是否可以使用和如何使用NoSQL数据库的企业提供了可靠的决策依据。它由世界级软件开发大师和软件开发“教父”Martin Fowler与Jolt生产效率大奖图书作者Pramod J. Sadalage共同撰写。书中全方位比较了关系型数据库与NoSQL数据库的异同;分别以Riak、MongoDB、Cassandra和Neo4J为代表,详细讲解了键值数据库、文档数据库、列族数据库......一起来看看 《NoSQL精粹》 这本书的介绍吧!