Spring中使用事务需要添加注解,表示开启事务
@EnableTransactionManagement
这个注解有个默认属性
AdviceMode mode() default AdviceMode.PROXY;
说明默认是使用JDK代理的通知模式。
然后注解上面使用了@Import注解
@Import(TransactionManagementConfigurationSelector.class)
我们再来看TransactionManagementConfigurationSelector这个类。
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
这个selectImports()方法返回了ProxyTransactionManagementConfiguration和AutoProxyRegistrar的全路径名,其中ProxyTransactionManagementConfiguration设置了
BeanFactoryTransactionAttributeSourceAdvisor2个属性TransactionInterceptor和TransactionAttributeSource,其中TransactionAttributeSource的实现类是AnnotationTransactionAttributeSource()。实例化的时候还指定了解析类是SpringTransactionAnnotationParser。
核心原理就是:SpringTransactionAnnotationParser解析@Transactional注解的类,将属性设置到TransactionAttributeSource中,然后调用方法时由拦截器TransactionInterceptor拦截实现事务的代理,使用PlatformTransactionManager来管理事务。
因为我标注在@Controller上了,调用顺序如下
--》AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
--》initializeBean(beanName, exposedObject, mbd)
---》applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName)
--》Object current = processor.postProcessAfterInitialization(result, beanName);
--》wrapIfNecessary(bean, beanName, cacheKey)
--》Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));//这里的specificInterceptors就是BeanFactoryTransactionAttributeSourceAdvisor对象。
--》return proxyFactory.getProxy(getProxyClassLoader());
这个就是返回的代理类了,调用这个方法的时候直接就是使用了代理类的方法。
当我调用@Transactional标注的接口时,会调用org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept方法。
--》org.springframework.aop.framework.ReflectiveMethodInvocation#proceed
--》return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)
--》org.springframework.transaction.interceptor.TransactionInterceptor#invoke
因为我用了MySQL数据库,连接池是Hikari连接池,这里的事务管理器是DataSourceTransactionManager,该管理器实现了PlatformTransactionManager接口。
接下来是真正的事务管理了
// 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();
如果抛异常
completeTransactionAfterThrowing(txInfo, ex);
然后finally
cleanupTransactionInfo(txInfo);
如果成功了
commitTransactionAfterReturning(txInfo);
底层是
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
总结:
多看看TransactionAspectSupport#invokeWithinTransaction方法,这里是Spring的事务管理器的逻辑