一、 如何实现动态事务
如何实现其实就是遇到问题和解决问题的过程。
- 如何知道这个方法需要开启事务?
答:只要给这个方法打上一个标记,有标记的方法就被认为需要开启事务。就像别人给你一块糖,不管它是什么糖,是大的、小的、方的、还是圆的。 - 虽然有了标记,但是这个标记如何被处理?
答:需要能解析这个标记的程序来处理标记,也就是开启事务。
就像别人给了你一块糖,你要能把糖吃到嘴里。如果你不知道如何打开包装,吃不到,那这个糖就不是糖了。
综上所述,我们需要两个东西来实现,一个是标记,另一个就是解析标记的程序。可以说spring体系下实现的功能大都需要这两样东西。
二、spring-boot 实现事务需要的基础知识
- spring-boot 查找bean的流程
- spring-context 初始化流程
- spring-aop 流程
三、spring-boot实现流程
- 把需要事务的对象交个spring管理
- 给需要的方法打上标记,即@Transactional 注解
- 把解析标记的程序交给spring。这个程序并不需要我们自己写,spring已经写好了,即TransactionInterceptor对象。默认spring-boot自动实现了这个流程。
- 需要spring-aop。@Transactional 标记的方法作为pointcut
,TransactionInterceptor作为advice。默认spring-boot自动实现了这个流程。
四、spring-boot事务实现原理
实现原理,主要写上面所说的3,4两个流程。
- spring-boot 查找bean的流程中其中一步是读取jar文件下的spring.factories文件并加载其中的类。这里加载了org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration 类。下面是这个类部分代码。
public class TransactionAutoConfiguration {
public static class EnableTransactionManagementConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = true)//这个注解是事务实现的入口
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
}
}
- @EnableTransactionManagement 加载了两个对象
- org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration :将@Transactional标记包装成切点,TransactionInterceptor包装advice,创建了实现Advisor(aop 使用该接口)接口的对象
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
//该bean实现了Advisor接口,aop会查找该接口的对象,并实现调用代理transactionInterceptor中的开启事务方法
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource,
TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
//代表@Transactional 注解的对象
@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();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
- org.springframework.context.annotation.AutoProxyRegistrar :开启aop能力;向spring注入了org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator 对象,该对象会拦截其他对象的创建并生成代理对象;AnnotationAwareAspectJAutoProxyCreator 实现了BeanPostProcessor,在spring-context加载bean的流程中会调用如下方法(AnnotationAwareAspectJAutoProxyCreator祖先类中定义)
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 这里会查找所有实现Advisor接口的对象,并生成代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}