平时我们都是使用注解开启事务@EnableTransactionManagement
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
//proxyTargetClass = false表示是JDK动态代理支持接口代理。true表示是Cglib代理支持子类继承代理。
boolean proxyTargetClass() default false;
//事务通知模式(切面织入方式),默认代理模式(同一个类中方法互相调用拦截器不会生效),可以选择增强型AspectJ
AdviceMode mode() default AdviceMode.PROXY;
//同一个类中方法互相调用拦截器不会生效,是因为重点在于,Spring采用动态代理(AOP)实现对bean的管理和切片,它为我们的每个class生成一个代理对象。只有在代理对象之间进行调用时,可以触发切面逻辑。
//而在同一个class中,方法B调用方法A,调用的是原对象的方法,而不通过代理对象。所以Spring无法切到这次调用,也就无法通过注解保证事务性了。
// 也就是说,在同一个类中的方法调用,则不会被方法拦截器拦截到,因此事务不会起作用。
//解决方法1:
//将事务方法放到另一个类中(或者单独开启一层,取名“事务层”)进行调用,即符合了在对象之间调用的条件。
//解决方法2:
//获取本对象的代理对象,再进行调用。具体操作如:
1) Spring-content.xml上下文中,增加配置:<aop:aspectj-autoproxy expose-proxy="true"/>
2) 在xxxServiceImpl中,用(xxxService)(AopContext.currentProxy()),获取到xxxService的代理类,再调用事务方法,强行经过代理类,激活事务切面。
//解决方法3:
//很多时候,方法内调用又希望激活事务,是由于同一个方法既有DAO操作又有I/O等耗时操作,不想让耗时的I/O造成事务的太长耗时(比如新增商品同时需要写入库存)。此时,可以将I/O做成异步操作(如加入线程池),而加入线程池的操作即便加入事务也不会导致事务太长,问题可以迎刃而解。
//解决方法4:
//用@Autowired 注入自己 然后在用注入的bean调用自己的方法也可以
//连接点上有多个通知时,排序,默认最低。值越大优先级越低。
int order() default Ordered.LOWEST_PRECEDENCE;
}
重点看类注解@Import(TransactionManagementConfigurationSelector.class)
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
/**
* Returns {@link ProxyTransactionManagementConfiguration} or
* {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
* and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
* respectively.
*/
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
// 向Spring中添加了AutoProxyRegistrar和ProxyTransactionManagementConfiguration对应的bean
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
// 不考虑
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}
最终会执行selectImports方法导入需要加载的类,我们只看proxy模式下,载入了AutoProxyRegistrar、ProxyTransactionManagementConfiguration2个类。
- AutoProxyRegistrar:
给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
- ProxyTransactionManagementConfiguration:就是一个配置类,定义了事务增强器。
AutoProxyRegistrar
先看AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,复写registerBeanDefinitions方法,源码如下:
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
/**
* Register, escalate, and configure the standard auto proxy creator (APC) against the
* given registry. Works by finding the nearest annotation declared on the importing
* {@code @Configuration} class that has both {@code mode} and {@code proxyTargetClass}
* attributes. If {@code mode} is set to {@code PROXY}, the APC is registered; if
* {@code proxyTargetClass} is set to {@code true}, then the APC is forced to use
* subclass (CGLIB) proxying.
* <p>Several {@code @Enable*} annotations expose both {@code mode} and
* {@code proxyTargetClass} attributes. It is important to note that most of these
* capabilities end up sharing a {@linkplain AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME
* single APC}. For this reason, this implementation doesn't "care" exactly which
* annotation it finds -- as long as it exposes the right {@code mode} and
* {@code proxyTargetClass} attributes, the APC can be registered and configured all
* the same.
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
// 获取EnableTransactionManagement注解的属性值
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
// 注册一个InfrastructureAdvisorAutoProxyCreator类型的Bean
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
logger.info(String.format("%s was imported but no annotations were found " +
"having both 'mode' and 'proxyTargetClass' attributes of type " +
"AdviceMode and boolean respectively. This means that auto proxy " +
"creator registration and configuration may not have occurred as " +
"intended, and components may not be proxied as expected. Check to " +
"ensure that %s has been @Import'ed on the same class where these " +
"annotations are declared; otherwise remove the import of %s " +
"altogether.", name, name, name));
}
}
}
代理模式:AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
-------
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
registerOrEscalateApcAsRequired基础构建增强自动代理构造器
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//如果当前注册器包含internalAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) { //如果当前类不是internalAutoProxyCreator
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {//如果下标大于已存在的内部自动代理构造器,index越小,优先级越高,InfrastructureAdvisorAutoProxyCreator index=0,requiredPriority最小,不进入
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;//直接返回
}
//如果当前注册器不包含internalAutoProxyCreator,则把当前类作为根定义
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
第一次会走到//如果当前注册器不包含internalAutoProxyCreator,则把当前类作为根定义 这边
那么增强代理类何时生成呢?
InfrastructureAdvisorAutoProxyCreator类图如下:
看2个核心方法:InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation实例化前+BeanPostProcessor接口的postProcessAfterInitialization初始化后
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// advisedBeans中存的是当前这个bean需不需要代理
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// 当前bean是不是不需要进行代理
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
//添加进advisedBeans ConcurrentHashMap<k=Object,v=Boolean>标记是否需要增强实现,这里基础构建bean不需要代理,都置为false,供后面postProcessAfterInitialization实例化后使用。
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 查看是否需要提前生成代理对象
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
// 判断当前beanClass和beanName是否会生成一个TargetSource,如果生成了,就进行代理
// TargetSource是spring aop预留给我们用户自定义实例化的接口,如果存在TargetSource就不会默认实例化,而是按照用户自定义的方式实例化,咱们没有定义,不进入
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 创建一个代理对象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
通过追踪,由于InfrastructureAdvisorAutoProxyCreator是基础构建类,
advisedBeans.put(cacheKey, Boolean.FALSE)
添加进advisedBeans
// advisedBeans 中存储的是 class:是否应该被代理
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
这里基础构建bean不需要代理,都置为false,供后面postProcessAfterInitialization实例化后使用。
我们再看postProcessAfterInitialization源码如下:
@Override
// 正常情况进行AOP的地方
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// earlyProxyReferences中存的是哪些提前进行了AOP的bean,beanName:AOP之前的对象
// 注意earlyProxyReferences中并没有存AOP之后的代理对象 BeanPostProcessor
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 没有提前进行过AOP,则进行AOP
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
// 为什么不返回代理对象呢?
//没有进行AOP ,所以直接返回原始对象
return bean; //
}
下面的方法都会走进去一般 在下面的方法判断是否需要Aop
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 在当前targetSourcedBeans中存在的bean,表示在实例化之前就产生了代理对象
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 当前这个bean不用被代理
// 查询map缓存,标记过false,不需要增强直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 先判断当前bean是不是要进行AOP,比如当前bean的类型是Pointcut、Advice、Advisor等那就不需要进行AOP
// 判断一遍springAOP基础构建类,标记过false,不需要增强直接返回
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 获取当前beanClass所匹配的advisors
// 获取增强List<Advisor> advisors
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// 如果匹配的advisors不等于null,那么则进行代理,并返回代理对象
if (specificInterceptors != DO_NOT_PROXY) { // 如果存在增强
// 标记增强为TRUE,表示需要增强实现 // 生成增强代理类
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 基于bean对象和Advisor创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// 存一个代理对象的类型
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 如果不存在增强,标记false,作为缓存,再次进入提高效率 利用前面的缓存先校验
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 如果是ConfigurableListableBeanFactory接口(咱们DefaultListableBeanFactory就是该接口的实现类)则,暴露目标类
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
//给beanFactory->beanDefinition定义一个属性:k=AutoProxyUtils.originalTargetClass,v=需要被代理的bean class
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this); // 复制配置参数
// 是否指定了必须用cglib进行代理
if (!proxyFactory.isProxyTargetClass()) {
// 如果没有指定,那么则判断是不是应该进行cglib代理(判断BeanDefinition中是否指定了要用cglib)
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 是否进行jdk动态代理,如果当前beanClass实现了某个接口,那么则会使用JDK动态代理
evaluateProxyInterfaces(beanClass, proxyFactory); // 判断beanClass有没有实现接口
}
}
// 将commonInterceptors和specificInterceptors整合再一起
//把拦截器包装成增强(通知)
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors); // 向ProxyFactory中添加advisor
proxyFactory.setTargetSource(targetSource); // 被代理的对象
customizeProxyFactory(proxyFactory);//空方法,留给子类拓展用,典型的spring的风格,喜欢处处留后路
//用于控制代理工厂是否还允许再次添加通知,默认为false(表示不允许)
proxyFactory.setFrozen(this.freezeProxy); //默认false,上面已经前置过滤了匹配的增强Advisor
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 生成代理对象
//代理工厂获取代理对象的核心方法
return proxyFactory.getProxy(getProxyClassLoader());
}
最终我们生成的是CGLIB代理类.到此为止我们分析完了代理类的构造过程。
接下来看第二个添加的ProxyTransactionManagementConfiguration
@Configuration(proxyBeanMethods = false)
public class
ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)//定义事务增强器
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, // AnnotationTransactionAttributeSource
TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource); // 表示的切点
advisor.setAdvice(transactionInterceptor); // 表示Advice,代理逻辑
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)//定义基于注解的事务属性资源
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)//定义事务拦截器
public TransactionInterceptor transactionInterceptor(
TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
// 拦截器中持有@Transactional注解的信息
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
其中切点
advisor.setTransactionAttributeSource(transactionAttributeSource); // 表示的切点
@SuppressWarnings("serial")
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
// 构造了一个PointCut, TransactionAttributeSource的实现对象为AnnotationTransactionAttributeSource
// 在PointCut匹配类时,会利用AnnotationTransactionAttributeSource去检查类上是否有@Transactional注解
// 在PointCut匹配方法时,会利用AnnotationTransactionAttributeSource去检查方法上是否有@Transactional注解
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
/**
* Set the transaction attribute source which is used to find transaction
* attributes. This should usually be identical to the source reference
* set on the transaction interceptor itself.
* @see TransactionInterceptor#setTransactionAttributeSource
*/
public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}
/**
* Set the {@link ClassFilter} to use for this pointcut.
* Default is {@link ClassFilter#TRUE}.
*/
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
其中TransactionAttributeSourcePointcut 判断类后者方法上 是否存在@Transactional的注解 需要代理
@SuppressWarnings("serial")
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
protected TransactionAttributeSourcePointcut() {
setClassFilter(new TransactionAttributeSourceClassFilter());
}
// 某个类或方法上是否存在@Transactional注解
@Override
public boolean matches(Method method, Class<?> targetClass) {
// AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
// 某个类或方法上是否存在@Transactional注解
// 调用AnnotationTransactionAttributeSource的父类中的getTransactionAttribute()方法
// 判断是否存在@Transactional注解,获取到该注解的信息,不等于null则匹配
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
@Override
public boolean equals(@Nullable Object other) {
if (this == other) {
return true;
}
if (!(other instanceof TransactionAttributeSourcePointcut)) {
return false;
}
TransactionAttributeSourcePointcut otherPc = (TransactionAttributeSourcePointcut) other;
return ObjectUtils.nullSafeEquals(getTransactionAttributeSource(), otherPc.getTransactionAttributeSource());
}
@Override
public int hashCode() {
return TransactionAttributeSourcePointcut.class.hashCode();
}
@Override
public String toString() {
return getClass().getName() + ": " + getTransactionAttributeSource();
}
/**
* Obtain the underlying TransactionAttributeSource (may be {@code null}).
* To be implemented by subclasses.
*/
@Nullable
protected abstract TransactionAttributeSource getTransactionAttributeSource();
/**
* {@link ClassFilter} that delegates to {@link TransactionAttributeSource#isCandidateClass}
* for filtering classes whose methods are not worth searching to begin with.
*/
private class TransactionAttributeSourceClassFilter implements ClassFilter {
@Override
public boolean matches(Class<?> clazz) {
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
PlatformTransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
// 获取到AnnotationTransactionAttributeSource对象
TransactionAttributeSource tas = getTransactionAttributeSource();
// 类上是否存在@Transactional注解
return (tas == null || tas.isCandidateClass(clazz));
}
}
}
其中看下getTransactionAttributeSource方法是由AbstractFallbackTransactionAttributeSource提供(AnnotationTransactionAttributeSource的父类)
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
Object cacheKey = getCacheKey(method, targetClass);
// 缓存了@Transactional注解的信息
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
// We need to work it out.
// 获取@Transactional注解的信息
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
其中computeTransactionAttribute
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Don't allow no-public methods as required.
// allowPublicMethodsOnly默认为true,所以在非public方法上写的@Transactional注解没有作用
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// First try is the method in the target class.
// 方法上@Transactional注解的信息
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// Second try is the transaction attribute on the target class.
// 类上@Transactional注解的信息
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
if (specificMethod != method) {
// Fallback is to look at the original method.
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// Last fallback is the class of the original method.
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
所以可以看出在非public方法上写的@Transactional注解没有作用 即不通过aop代理了
下面举个例子
举个例子 如下的例子其实a()方法等于木有@Tran注解 那么由于spring在创建代理对象打的时候之后会往原始对象注入值(这里的usermapper)那么就造成了
直接执行代理对象的的a()方法 就返回npe 除非这里@Tran注解生效那么代理对象就会执行原始对象的a方法这样usermapper就有值了
核心方法:transactionAdvisor()事务织入
定义了一个advisor,设置事务属性、设置事务拦截器TransactionInterceptor、设置顺序。核心就是事务拦截器TransactionInterceptor。
TransactionInterceptor使用通用的spring事务基础架构实现“声明式事务”,继承自TransactionAspectSupport类(该类包含与Spring的底层事务API的集成),实现了MethodInterceptor接口
事务拦截器的拦截功能就是依靠实现了MethodInterceptor接口,熟悉spring的同学肯定很熟悉MethodInterceptor了,这个是spring的方法拦截器,主要看invoke方法:
@Override
@Nullable
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);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
// 执行代理逻辑
// 调用TransactionAspectSupport的 invokeWithinTransaction方法
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
TransactionInterceptor复写MethodInterceptor接口的invoke方法,并在invoke方法中调用了父类TransactionAspectSupport的invokeWithinTransaction()方法,源码如下:
@Nullable
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中(attributeCache属性)记录了系统中每个Bean的每个方法上@Transactional注解的信息(可能为null)
TransactionAttributeSource tas = getTransactionAttributeSource();
// 如果transaction attribute为空,该方法就是非事务(非编程式事务)
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 得到一个TransactionManager
final TransactionManager tm = determineTransactionManager(txAttr);
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.getAdapter(method.getReturnType());
if (adapter == null) {
throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
method.getReturnType());
}
return new ReactiveTransactionSupport(adapter);
});
return txSupport.invokeWithinTransaction(
method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
}
// 转化为PlatformTransactionManager
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
// 根据当前执行的类中的某个方法以及@Transactional注解的信息生成一个唯一标志,这个标记会用来作为事务名
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 标准声明式事务:如果事务属性为空 或者 非回调偏向的事务管理器
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
// 创建事务,并得到事务信息,后面需要事务信息用来进行提交或回滚
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
// 执行业务方法逻辑
// 这里就是一个环绕增强,在这个proceed前后可以自己定义增强实现
// 方法执行
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
// 出现异常的情况下,如果异常需要rollback,则回滚,否则则会提交
completeTransactionAfterThrowing(txInfo, ex);
// 出现异常后会先执行finally中的方法逻辑在抛出当前异常
throw ex;
}
finally {
// 清除ThreadLocal中的事务信息
cleanupTransactionInfo(txInfo);
}
if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
// 提交事务
//返回结果之前提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
// 编程式事务:(回调偏向)
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
try {
Object retVal = invocation.proceedWithInvocation();
if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
return retVal;
}
catch (Throwable ex) { // 如果该异常需要回滚
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {// 如果是其它异常都抛ThrowableHolderException
throw new ThrowableHolderException(ex);
}
}// 如果不需要回滚
else {
// A normal return value: will lead to a commit.
// 定义异常,最终就直接提交事务了
throwableHolder.throwable = ex;
return null;
}
}
finally {//清空当前事务信息,重置为老的
cleanupTransactionInfo(txInfo);
}
});
// 上抛异常
// Check result state: It might indicate a Throwable to rethrow.
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}
先从
// 转化为PlatformTransactionManager
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
看起
@Nullable
private PlatformTransactionManager asPlatformTransactionManager(@Nullable Object transactionManager) {
if (transactionManager == null || transactionManager instanceof PlatformTransactionManager) {
return (PlatformTransactionManager) transactionManager;
}
else {
throw new IllegalStateException(
"Specified transaction manager is not a PlatformTransactionManager: " + transactionManager);
}
}
也就是说不是PlatformTransactionManager就抛异常 我们一般用的是 其子类DataSourceTransactionManager
接着看
// 创建事务,并得到事务信息,后面需要事务信息用来进行提交或回滚
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
@SuppressWarnings("serial")
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// If no name specified, apply method identification as transaction name.
// 事务的名字
if (txAttr != null && txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
}
};
}
// 得到一个标识事务状态的对象()
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
status = tm.getTransaction(txAttr);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
"] because no transaction manager has been configured");
}
}
}
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
接着看
status = tm.getTransaction(txAttr);
会走到AbstractPlatformTransactionManager(上面我们说的DataSourceTransactionManager的父类)的getTransaction方法
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// Use defaults if no transaction definition given.
// TransactionDefinition就是TransactionAttribute,就是@Transactional注解信息
// 表示一个事务的定义,通过@Transactional注解也就是在定义一个事务
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 获取一个事务对象,每次都会生成一个DataSourceTransactionObject,而重点是这个对象中是否已经存在一个数据库连接
//一个数据库连接就是一个事物
Object transaction = doGetTransaction(); //
boolean debugEnabled = logger.isDebugEnabled();
// 如果已经存在一个数据库连接,表示当前线程已经存在一个事务
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
// 存在事务的情况下,按不同的传播级别进行处理
return handleExistingTransaction(def, transaction, debugEnabled);
}
// Check definition settings for new transaction.
// timeout如果为-1,表示没有时间限制
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// 当前线程还不存在事务
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 挂起
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 事务对象中包括:
// 1. 事务的定义
// 2. 事务对象
// 3. 是否是新事务
DefaultTransactionStatus status = newTransactionStatus(
def, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 开启事务,获得新的Connection对象
doBegin(transaction, def);
// 初始化TransactionSynchronizationManager中的属性
prepareSynchronization(status, def);
return status;
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// 不会doBegin,不会真的开启事务,也就是不会把Connection的autoCommit设置为false,sql没有在事务中执行
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + def);
}
//
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
}
继续走到doGetTransaction();
@Override
protected Object doGetTransaction() {
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed()); // 是否允许嵌套事务,默认是允许的,在DataSourceTransactionManager无参构造方法中进行了设置
// 从当前线程ThreadLocal中获取当前DataSource所对应的数据库连接,可能为null 第一次开启事务的时候走过来就是null 如举例子的test方法
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
继续看getResource
@Nullable
public static Object getResource(Object key) {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Object value = doGetResource(actualKey);
if (value != null && logger.isTraceEnabled()) {
logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
Thread.currentThread().getName() + "]");
}
return value;
}
继续看doGetResource
@Nullable
private static Object doGetResource(Object actualKey) {
// resources是一个ThreadLocal,表示每个线程中缓存的某个DataSource对应的数据库连接
Map<Object, Object> map = resources.get();
if (map == null) {
return null;
}
Object value = map.get(actualKey);
// Transparently remove ResourceHolder that was marked as void...
if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
map.remove(actualKey);
// Remove entire ThreadLocal if empty...
if (map.isEmpty()) {
resources.remove();
}
value = null;
}
return value;
}
-------
// key为datasource,value为某个数据库连接
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
回到getTransaction继续看 DataSourceTransactionManager 覆写了 isExistingTransaction
/// 如果某个事务对象已经设置了数据库连接,那么则表示当前这个事务是正存在的事务
@Override
protected boolean isExistingTransaction(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}
回到getTransaction继续看
// 挂起
SuspendedResourcesHolder suspendedResources = suspend(null);
@Nullable
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
if (TransactionSynchronizationManager.isSynchronizationActive()) { // 当前线程中是否同步了事务信息
List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
try {
// 先把事务挂起
Object suspendedResources = null;
if (transaction != null) {
// 把当前事务对象中的数据库连接清空并把它返回
suspendedResources = doSuspend(transaction);
}
// 再把线程中记录的之前事务的信息清空,并记录到SuspendedResourcesHolder中
String name = TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.setCurrentTransactionName(null);
boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
TransactionSynchronizationManager.setActualTransactionActive(false);
// 把当前挂起的事务的所有信息全部存在SuspendedResourcesHolder中
// 包括连接对象,同步器,事务名字,隔离级别
return new SuspendedResourcesHolder(
suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
}
catch (RuntimeException | Error ex) {
// doSuspend failed - original transaction is still active...
doResumeSynchronization(suspendedSynchronizations);
throw ex;
}
}
else if (transaction != null) {
// Transaction active but no synchronization active.
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
}
else {
// Neither transaction nor synchronization active.
return null;
}
}
DataSourceTransactionManager 覆写了 doSuspend 可以看出把持有的连接tConnectionHolder 设置为了空 一个线程只能有一个正在执行的事务 要执行新的事务 旧的事务得挂起 (只能按顺序执行 不能并行执行)
@Override
protected Object doSuspend(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
txObject.setConnectionHolder(null);
return TransactionSynchronizationManager.unbindResource(obtainDataSource());
}
再看doBegin 也是DataSourceTransactionManager中的
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
// 如果事务对象内没有连接就从dataSource中获取一个连接
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
// isSynchronizedWithTransaction 我的理解,表示连接是否和事务同步,表示每开启一个事务就从DataSource中获取一个连接
// 默认是false,所以在开启事务时,除非当前事务对象中还没有数据库连接才会从DataSource中去获取一个连接
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
// 设置为newConnectionHolder为true
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
// 如果在开启事务时,事务对象中已经有数据库连接了
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
// 设置数据库连接的隔离级别
// 如果当前事务中的隔离级别跟数据库的隔离级别不一样就返回数据库的隔离级别并记录下来,事务结束后恢复
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
txObject.setReadOnly(definition.isReadOnly());
// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
// 把数据库连接的autoCommit设置为false,禁止数据库的自动提交
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
con.setAutoCommit(false);
}
prepareTransactionalConnection(con, definition);
txObject.getConnectionHolder().setTransactionActive(true);
// 设置数据库连接的超时时间
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// Bind the connection holder to the thread.
if (txObject.isNewConnectionHolder()) {
// 把新生成的数据库连接设置到当前线程的TheadLocal中进行缓存
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
}
catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
接着回到invokeWithinTransaction 看completeTransactionAfterThrowing
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
"] after exception: " + ex);
}
// 如果当前异常需要回滚,则回滚,否则则提交
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
}
}
else {
// We don't roll back on this exception.
// Will still roll back if TransactionStatus.isRollbackOnly() is true.
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by commit exception", ex);
throw ex2;
}
}
}
}
看到rollbackOn方法是DefaultTransactionAttribute里面的
@Override
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
可以看出默认回滚类型是RuntimeException和error
接着看rollback方法 调用的是AbstractPlatformTransactionManager
@Override
public final void rollback(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
processRollback(defStatus, false);
}
---------
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
try {
boolean unexpectedRollback = unexpected;
try {
// 触发同步器的beforeCompletion()
triggerBeforeCompletion(status);
// 如果有savepoint,则回滚到安全点
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
}
status.rollbackToHeldSavepoint();
}
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback");
}
doRollback(status);
}
else {
// Participating in larger transaction
if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
}
doSetRollbackOnly(status);
}
else {
if (status.isDebug()) {
logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
}
}
}
else {
logger.debug("Should roll back transaction but cannot - no transaction available");
}
// Unexpected rollback only matters here if we're asked to fail early
if (!isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = false;
}
}
}
catch (RuntimeException | Error ex) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
}
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
// Raise UnexpectedRollbackException if we had a global rollback-only marker
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
}
finally {
cleanupAfterCompletion(status);
}
}
接着
// 提交事务
commitTransactionAfterReturning(txInfo);
调用commit
@Override
public final void commit(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
processRollback(defStatus, false);
return;
}
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
processRollback(defStatus, true);
return;
}
processCommit(defStatus);
}
TransactionInterceptor执行流程
简单版流程
- 生成test事务状态对象
- test事务doBegin,获取并将数据库连接2825设置到test事务状态对象中
- 把test事务信息设置到事务同步管理器中
- 执行test业务逻辑方法(可以获取到test事务的信息)
-
- 生成a事务状态对象,并且可以获取到当前线程中已经存在的数据库连接2825
- 判断出来当前线程中已经存在事务
- 如果需要新开始事务,就先挂起数据库连接2825,挂起就是把test事务信息从事务同步管理器中转移到挂起资源对象中,并把当前a事务状态对象中的数据库连接设置为null
- a事务doBegin,新生成一个数据库连接2826,并设置到a事务状态对象中
- 把a事务信息设置到事务同步管理器中
- 执行a业务逻辑方法(可以利用事务同步管理器获取到a事务信息)
- 利用a事务状态对象,执行提交
- 提交之后会恢复所挂起的test事务,这里的恢复,其实只是把挂起资源对象中所保存的信息再转移回事务同步管理器中
- 继续执行test业务逻辑方法(仍然可以获取到test事务的信息)
- 利用test事务状态对象,执行提交
传播机制
举例子
情况1
@Component
public class UserService {
@Autowired
private UserService userService;
@Transactional
public void test() {
// test方法中的sql
userService.a();
}
@Transactional
public void a() {
// a方法中的sql
}
}
默认情况下传播机制为REQUIRED
所以上面这种情况的执行流程如下:
- 新建一个数据库连接conn
- 设置conn的autocommit为false
- 执行test方法中的sql
- 执行a方法中的sql
- 执行conn的commit()方法进行提交
情况2
假如是这种情况
@Component
public class UserService {
@Autowired
private UserService userService;
@Transactional
public void test() {
// test方法中的sql
userService.a();
int result = 100/0;
}
@Transactional
public void a() {
// a方法中的sql
}
}
所以上面这种情况的执行流程如下:
- 新建一个数据库连接conn
- 设置conn的autocommit为false
- 执行test方法中的sql
- 执行a方法中的sql
- 抛出异常
- 执行conn的rollback()方法进行回滚
情况3
假如是这种情况:
@Component
public class UserService {
@Autowired
private UserService userService;
@Transactional
public void test() {
// test方法中的sql
userService.a();
}
@Transactional
public void a() {
// a方法中的sql
int result = 100/0;
}
}
所以上面这种情况的执行流程如下:
- 新建一个数据库连接conn
- 设置conn的autocommit为false
- 执行test方法中的sql
- 执行a方法中的sql
- 抛出异常
- 执行conn的rollback()方法进行回滚
情况4
如果是这种情况:
@Component
public class UserService {
@Autowired
private UserService userService;
@Transactional
public void test() {
// test方法中的sql
userService.a();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void a() {
// a方法中的sql
int result = 100/0;
}
}
所以上面这种情况的执行流程如下:
- 新建一个数据库连接conn
- 设置conn的autocommit为false
- 执行test方法中的sql
- 又新建一个数据库连接conn2
- 执行a方法中的sql
- 抛出异常
- 执行conn2的rollback()方法进行回滚
- 继续抛异常
- 执行conn的rollback()方法进行回滚
不加@tan的注解就不是同一个事务了 因为 一般sql 是自动开启事务的也就是说一句sql是一个事物
传播机制
conn1挂起到conn1恢复是 执行a方法
嵌套的事务
这里就有个保存点的概念 下面rollback xxx 那么之后回滚 sql3和sql4 除非只写 rollback 那么全部回滚
这种情况只有一个数据库连接 跟上面的默认情况不同
TransactionSynchronizationManager 一个线程只能有一个正在执行的事务 要执行新的事务 旧的事务得挂起 (只能按顺序执行 不能并行执行)
两个事务的执行流程 类似线程上下文切换那样的
mybatis怎么拿到spirng所创建的事物连接的