spring事务源码-代理对象生成过程解析

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

  1. AutoProxyRegistrar
  2. 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
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值