spring的事务有两种,一种是声明是事务,一种是编程式事务,这里我们讲的是基于注解实现的方式,为什么我们在一个方法上面加上一个@Transactional注解,程序就能自动管理我们的本地事务,我们知道在SpringBoot项目中要用到Spring的事务,在启动配置类上面要加一个@EnableTransactionManagement,我们看看这个注解为我们做了些什么东西,
可以很明显看到这个是一个组合注解,通过Import注解给我们导入了一个叫做TransactionManagementConfigurationSelector的一个selector,熟悉spring源码的应该知道selector,和registar是spring提供了两个扩展点,在spring容器启动时候,在解析配置类转换为BeanDefinition定义时候,会完成相应的解析处理,继续看这个TransactionManagementConfigurationSelector类
spring容器启动的时候,当解析这个selector时候会回调这个selectImports方法,这里就会进入PROXY分支,为我们注册一个AutoProxyRegistar,和一个ProxyTransactionManagementConfiguration配置类。分别进入这两个类里面,
AutoProxyRegistar实现了ImportBeanDefinitionRegistar,在容器启动解析配置文件的时候会触发registerBeanDefinitions方法,在这个方法里面会调用到AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)这个方法,继续点击进去
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source)
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
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;
}
最终会在容器里面注册和实例化一个叫InfrastructureAdvisorAutoProxyCreator的类,而这个类的继承关系可以看到
这个类实现了BeanPostProcessor后置处理器,在创建bean的时候会调用后置处理器,完成一些bean的扩展和增强,spring容器启动实例化Bean的时候会调用BeanPostProcessor的postProcessAfterInitialization方法将所有加了@Trancation注解的方法封装到一个个advistor到代理类里面,后续方法调用的时候会拿出来处理
ProxyTransactionManagementConfiguration配置类里面实例化了几个重要的类,
BeanFactoryTransactionAttributeSourceAdvisor 封装了事务切面的信息
TransactionAttributeSource 封装了事务属性信息
TransactionInterceptor 拦截事务方法执行的类
我们知道spring的事务是基于aop实现的,以jdk的动态代理来说,在带有事务注解的方法执行有事务的方法会调用到
JdkDynamicAopProxy这个类的invoke方法,我们看看这个invoke方法是如何执行的
这里会将前面spring容器启动时候封装的Advisor对象,转换一个拦截器链路,然后循环调用,在这里这个拦截器链是不为空的,所以会走else分支里面的逻辑,接着会调用invocation.proceed()方法
这里会走到else的invoke方法,最终会调用到TransactionInterceptor的invoke方法
这里看到了关键的invokeWithinTransaction方法,跟进去
这里有两个关键的方法,我们分别进去看看
很显然在捕获异常的时候进行了手动回滚事务,业务方法正常执行的情况就手动提交事务,到这里Spring事务源码分析就结束了