spring事务源码
spring事务的源码,要从@EnableTransactionManagement注解拉开序幕
首先,如果我们要使用spring事务,只需要在配置类上添加@EnableTransactionManagement注解,并且在业务方法上添加@Transactional注解即可(以spring项目为例,SpringBoot项目后面博客中再另说)
@EnableTransactionManagement
@Target({
ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({
TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
/*
* proxyTargetClass
* true:
* 无论目标方法是否实现了接口,都使用CGLIB代理
* false:
* 如果目标方法实现了接口,使用JDK动态代理
* 如果目标方法没有实现接口,使用CGLIB代理
*/
boolean proxyTargetClass() default false;
/**
* @return
*
* 事务通知模式(切面织入方式):
* 默认是代理模式
*/
AdviceMode mode() default AdviceMode.PROXY;
int order() default 2147483647;
}
可以看到,这个注解也挺简单的,就是通过@Import注解,引入了另外一个bean,通过查看TransactionManagementConfigurationSelector的类继承关系,可以发现,这个类实现了ImportSelector注解,所以,会实现selectImports()方法,在该方法中,注入了两个重要的bean
- AutoProxyRegistrar
- ProxyTransactionManagementConfiguration
AutoProxyRegistrar
AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,所以,在registerBeanDefinitions方法中,注入一个bean
InfrastructureAdvisorAutoProxyCreator
可以发现,这个类是一个后置处理器,继承了InstantiationAwareBeanPostProcessor
所以:这就是@EnableTransactionManagement的第一个作用,注入了一个后置处理器,这个后置处理器就是用来对事务注解进行增强的
ProxyTransactionManagementConfiguration
该类只有一个注解@Configuration,所以该类是一个配置类,在该类中,通过三个@Bean注解,向spring容器中注入了事务执行时要用到的组件
/**
* @return
* 注入事务增强器
* 这里是创建一个advisor,然后设置切点(TransactionInterceptor)和通知(TransactionAttributeSource)
* 这里的BeanFactoryTransactionAttributeSourceAdvisor类似于aop中的advisor
*/
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
//事务增强器会解析事务注解的参数信息
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
/**
* @return
* 往spring容器中注入事务解析器(解析事务注解上的各个参数)
* 在执行第八个后置处理器的时候,判断是否需要增强的时候,会解析transaction注解
*
* 这里在new AnnotationTransactionAttributeSource()对象的时候,有一个非常关键的点:
* publicMethodsOnly 这里在调用构造函数的时候,默认初始化该值为true;该值的意思是:只允许public方法进行事务代理
*
* 在后面判断是否可以对方法进行增强的时候,会判断该值,以及对应method是否是public,如果是非public修饰的方法,直接return null,不进行代理增强
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
/**
* @return
* 定义事务拦截器,并将事务拦截器注入到spring容器中
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
所以:该类是给spring容器中,注入了三个bean,分别是:事务拦截器、事务解析器、事务增强器
判断是否需要代理
我们知道,AOP的动态代理是在第八个后置处理器调用的时候,判断是否需要增强,如果需要增强,就通过JDK或者CGLIB进行代理,注解版的事务,也是利用了AOP实现的
这是在添加事务注解的方法对应的bean在初始化时,调用到第八个后置处理器的时候,判断是否需要进行增强的调用链,由于这里和AOP是一样的调用链,所以中间的这些过程就不做过多解释了,直接看最后匹配是否需要增强的代码
我们可以暂时先认为:methodMatcher.matches(method, targetClass) 如果这里返回的是true,就是需要进行增强,返回false,就继续遍历下一个方法,进行判断
org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches
// 这里是用获取到的tas来判断method是否有添加注解,如果这里返回false,就表示当前method无需增强,返回true,需要增强
public boolean matches(Method method, Class<?> targetClass) {
TransactionAttributeSource tas = this