Spring 事务管理 @Transactional 注解

之前,在研究了代理对象创建的原理以及如何包装advice通知之后,再来看一个例子:@Transactional注解

1.什么是@Transactional注解

举个例子:我们要往mysql数据库批量添加一些用户,比如说是2条,

定义一个controller层的方法:testAddUsers,

@PostMapping("/test")
public String testAddUsers(){
    userService.testAddUsers();
    return "testAddUsers OK!";
}

userserviceimpl的方法:

@Override
    @Transactional
    public void testAddUsers() {
        List<User> userList=new ArrayList<>();
        userList.add(new User().setUsername("mawebchao").setPassword("123"));
        userList.add(new User().setUsername("mawebchao").setPassword("123"));

        for (int i = 0; i < userList.size(); i++) {
            try {
                userMapper.insert(userList.get(i));
                if(i%2==0){
                    System.out.println(1/0);
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw e;
            }
        }
    }

因为加了Transactional注解,当方法体抛出异常之后,事务会回滚。这就是@Transactional注解的用处,它将整个方法体看作一个事务。

2.SpringTransactionAnnotationParser在什么时机去解析@Transactional注解的?猜测:spring容器refresh的时候

3.@Transactional注解加在方法上的时候,跟踪方法应该会成为一个advice,方法所在的类应该会成为一个代理对象,跟踪代理对象里的这个方法,和别的方法有什么区别

4.@EnableTransactionManagement配置类标识事务并运行方法和启动运用了事务的spring项目的时候,都会去执行SpringTransactionAnnotationParser的parseTransactionAnnotation方法,分别是为了干什么?

首先,执行 SpringTransactionAnnotationParser.parseTransactionAnnotation()方法,归根结底还是为了创建bean:

创建bean->判断是否需要生成代理对象->查找有没有符合的advisors->检查transactional注解

spring项目中和普通项目

加了@Springbootapplication注解后,在注解内部,spring自动定义了开启事务管理,而一旦开启了事务管理,事务管理的本质是方法的加强,所以和原始的aop一样,在容器中会多出一个transactionaladvice这个bean,这个只与是否开启事务有关。而普通项目没有加springbootapplication注解的话,可以加上@EnableTransactionManagement注解开启事务管理,起到的效果是一样的。但这里还有一个很大的区别在于,spring项目在refresh的regisBeanPostProcessor方法中就在做@Transactional注解的解析了,而普通方法中却是在finishBeanFactoryInitialization(创建剩余单例对象)的时候去解析的,这是为什么呢?

在spring项目中,在创建objectMapperConfigurer这个bean的时候,会去判断这个对象是否需要变成代理对象(所有对象创建的时候都要进行判断(wrapifnecessary方法)),而在加载objectMapperConfigurer它的预选advisors的时候把transactionaladvice给加进去了,所以需要判断

transactionaladvice是不是这个类的advice,所以才会去解析transactional注解(parseTransactionAnnotation方法)。所以为啥要解析@transactional注解呢,是为了判断当前这个类是否需要transactionaladvice对他进行加强。

那根据常理,一个类需要被transactionaladvice加强为代理对象的条件是什么?那最常用的就是它内部的某个方法或是某些方法加了@Transactional注解啊,所以看源码:

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass){
// First try is the method in the target class.
//找到目标类里被@Transactional注解的方法
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
// Second try is the transaction attribute on the target class.
//找到目标类里被@Transactional注解的属性
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
}

这里怎么找呢,首先要遍历类里所有的方法,再有parseTransactionAnnotation这个方法了------解析@Transactional注解,给他传递一个参数就是类里的方法method,那很显然objectMapperConfigurer这个类内部没有方法标注了@Transactional注解,所以First try的结果为null。Second try就更不用看了,肯定没有。。

那为什么会在创建objectMapperConfigurer这个bean的时候,预选者advisors里多了这个transactionaladvice呢?因为在objectMapperConfigurer的resolveBeforeInstantiation方法中已经间接创建了这个transactionaladvice了。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_34116044

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值