栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

基于Aop手写spring事务(声明式事务)

Java 更新时间:发布时间: 百科书网 趣学号

一、前言

   spring事务分为编程式事务和声明式事务。编程式事务需要自己手动开启,提交,回滚事务,声明式事务则是添加自带的Transactional注解就 ok,正常情况下就不用关心事务的操作了。

声明式事务优点:

声明式事务帮助我们节省了很多代码,他会自动帮我们进行事务的开启、提交以及回滚等操作,把程序员从事务管理中解放出来。

声明式事务管理使用了 AOP 实现的,本质就是在目标方法执行前后进行拦截。 在目标方法执行前加入或创建一个事务,在执行方法执行后,根据实际情况选择提交或是回滚事务。

使用这种方式,对代码没有侵入性,方法内只需要写业务逻辑就可以了。

声明式事务缺点:

声明式事务有一个局限,那就是他的最小粒度要作用在方法上。

也就是说,如果想要给一部分代码块增加事务的话,那就需要把这个部分代码块单独独立出来作为一个方法。

但是,正是因为这个粒度问题,本人并不建议过度的使用声明式事务。

首先,因为声明式事务是通过注解的,有些时候还可以通过配置实现,这就会导致一个问题,那就是这个事务有可能被开发者忽略。

事务被忽略了有什么问题呢?

首先,如果开发者没有注意到一个方法是被事务嵌套的,那么就可能会再方法中加入一些如RPC远程调用、消息发送、缓存更新、文件写入等操作。

二、编程式事务编写

1.导入依赖


        mysql
        mysql-connector-java
        5.1.47
    

    
        com.alibaba
        druid
        1.1.10
    
 @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;

    private TransactionStatus transaction;

    public TransactionStatus transactionBegin(){
        System.out.println("自定义事务开启");
        transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
        return transaction;
    }

    public void TransactionalCommit(){
        System.out.println("自定义事务提交");
        dataSourceTransactionManager.commit(transaction);
    }

    public void rollback(){
        System.out.println("自定义事务回滚");
        dataSourceTransactionManager.rollback(transaction);
    }

2.建表语句

CREATE TABLE `pe_user` (
  `id` varchar(40) NOT NULL COMMENT 'ID',
  `username` varchar(255) NOT NULL COMMENT '用户名称',
  `password` varchar(255) DEFAULT NULL COMMENT '密码',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3.测试代码

 public void add() {
        TransactionStatus transactionStatus = null;
        try{
                transactionStatus = transactionalUtil.transactionBegin();
                userMapper.insertUser("1232143243","dong","123");
                String aa = "18.239563";
                int i = Integer.parseInt(aa);
                System.out.println("插入user"+"dong" );
                userMapper.insertUser("sdsdwere120","ergouzi","456");
                transactionalUtil.TransactionalCommit();
            }catch (Exception e){
                transactionalUtil.rollback();
            }
    }

三、声明式事务

1.复用编程式事务代码

2.自定义声明式事务注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Transactional
public @interface MyTransaction {

    Propagation propagation() default Propagation.REQUIRED;

    Class[] rollbackFor() default {};
}

3.AOP切面编写

@Component
@Aspect
public class MyTransactionAop {
    @Autowired
    TransactionalUtil transactionalUtil;

    private TransactionStatus transactionStatus;

    @AfterThrowing(value = "execution(* com.dong.studyaop.service..*.*(..))",throwing = "e")
    public void afterThrowing(JoinPoint joinPoint,Exception e) throws Exception {
        //1.捕获到的异常是否属于配置的类型
        if (transactionStatus !=null){
            transactionalUtil.rollback();
        }
    }

    @Around("execution(* com.dong.studyaop.service..*.*(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //1.获取方法上的注解
        MyTransaction annotation = getAnnotation(proceedingJoinPoint);
        //2.开启事务
        begin(annotation);
        //3.执行目标对象的方法
        proceedingJoinPoint.proceed();
        //4.提交事务
        commit();
    }

    private void commit() {
        if (transactionStatus !=null){
            transactionalUtil.TransactionalCommit();
        }
    }

    private TransactionStatus begin(MyTransaction annotation) {
        if (annotation ==null){
            return null;
        }
        transactionStatus = transactionalUtil.transactionBegin();
        return transactionStatus;
    }

    private MyTransaction getAnnotation(JoinPoint proceedingJoinPoint) throws NoSuchMethodException {
        //1.获取代理对象的方法
        String name = proceedingJoinPoint.getSignature().getName();
        Class aClass = proceedingJoinPoint.getTarget().getClass();
        Class[] parameterTypes = ((MethodSignature) proceedingJoinPoint.getSignature()).getParameterTypes();
        //2.由代理对象获取目标对象的方法
        Method method = aClass.getMethod(name, parameterTypes);
        MyTransaction annotation = method.getAnnotation(MyTransaction.class);
        return annotation;
    }

4.测试代码

@Service
public class UserServiceImpl {

    @Resource
    UserMapper userMapper;

    @Autowired
    TransactionalUtil transactionalUtil;

    
    @MyTransaction
    public void add() {
            userMapper.insertUser("1232143243","dong","123");
            String aa = "18.239563";
            int i = Integer.parseInt(aa);
            System.out.println("插入user"+"dong" );
            userMapper.insertUser("sdsdwere120","ergouzi","456");
    }

    public void update() {

    }


}
转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/282113.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号