美文网首页Spring
【Spring】 11 - 关于 注解 配置 Spring AO

【Spring】 11 - 关于 注解 配置 Spring AO

作者: itlu | 来源:发表于2020-10-25 17:37 被阅读0次
    1. 问题 : 使用注解配置 Spring Aop 的四种通知类型实现事务控制,出现如下问题 :
      com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Can't call rollback when autocommit=true
    
    1. 原因:由于四种通知类型的执行顺序与 xml 配置方式的差异 ,可以将注解配置的方式理解为一个bug

    2. 正常使用 xml 配置 四种通知类型的执行顺序是 : 前置通知 后置通知/异常通知(当出现异常时) 最终通知。这是一种正常的情况。

         <aop:config>
            <aop:pointcut id="pc" expression="execution(* com.lyp.service.impl.*.*(..))"/>
            <aop:aspect id="txAspect" ref="txManager">
                <aop:before method="beginTransaction" pointcut-ref="pc"/>
                <aop:after-returning method="commitTransaction" pointcut-ref="pc"/>
                <aop:after-throwing method="rollbackTransaction" pointcut-ref="pc"/>
                <aop:after method="closeTransaction" pointcut-ref="pc"/>
            </aop:aspect>
        </aop:config>
    
    1. 使用注解配置四种通知类型的时候的执行顺序 :前置通知 最终通知 后置通知/异常通知(当出现异常时) 。此时最终通知优先于后置通知执行了,首先将连接释放,此时再进行提交,就是会出现上面的异常。
          /**
         * 开启事务
         */
        @Before("pc()")
        public void beginTransaction() {
            try {
                /* 设置事务提交方式为手动提交 */
                System.out.println("开启事务");
                cu.getTreadLocalConnection().setAutoCommit(false);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 回滚事务
         */
        @AfterReturning("pc()")
        public void rollbackTransaction() {
            try {
                /* 设置事务提交方式为手动提交 */
                System.out.println("回滚事务...");
                cu.getTreadLocalConnection().rollback();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 提交事务
         */
        @AfterThrowing("pc()")
        public void commitTransaction() {
            try {
                System.out.println("提交事务....");
                /* 设置事务提交方式为手动提交 */
                cu.getTreadLocalConnection().commit();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 释放连接
         */
        @After("pc()")
        public void closeTransaction() {
            try {
                /* 设置事务提交方式为手动提交 */
                System.out.println("关闭事务....");
                cu.getTreadLocalConnection().close();
                cu.removeConn();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    1. 解决办法:使用环绕通知替换上面的配置
    @Around("pc()")
    public Object aroundAdvice(ProceedingJoinPoint pjp) {
            Object rs = null;
            try {
                Object[] args = pjp.getArgs();
                // 开启事务
                this.beginTransaction();
                // 执行代码
                rs = pjp.proceed(args);
                // 提交事务
                this.commitTransaction();
                return rs;
            } catch (Throwable t) {
                // 回滚事务
                this.rollbackTransaction();
                throw new RuntimeException(t);
            } finally {
                this.closeTransaction();
            }
        }
    

    相关文章

      网友评论

        本文标题:【Spring】 11 - 关于 注解 配置 Spring AO

        本文链接:https://www.haomeiwen.com/subject/kfenmktx.html