关于srping的AOP事务管理问题,自定义切面是否导致事务控制失效

applicationContext.xml:

<!-- 方法调用时间记录 -->
    <bean id="methodExecuteTime" class="com.common.aspect.Aspect" />

    <!-- Spring AOP config (* com.customer.service.*.*(..))中几个通配符的含义: 第一个 * :通配
        任意返回值类型 第二个 * :通配 包com.customer.service下的任意class 第三个 * :通配 包com.customer.service下的任意class的任意方法
        第四个 .. :通配 方法可以有0个或多个参数 -->
    <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
    <aop:config proxy-target-class="true">
        <aop:pointcut id="serviceMethods" expression="execution(* com.customer.service..*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods" order="2" />

        <!--此处配置使得事务控制 回滚失效 暂时注释掉-->
        <!-- DB Service log -->
        <aop:aspect id="logThrsysServiceMethodExecuteTime" ref="methodExecuteTime" >
            <aop:pointcut id="thrsysServiceMethods" expression="execution(* com.customer.service..*.*(..))" />
            <aop:around method="methodExecuteTime" pointcut-ref="thrsysServiceMethods" />
        </aop:aspect>
    </aop:config>

当时在一个update开头的方法中有多个更新数据库的操作,为了测试事务回滚的有效性,在代码中放置了一段空指针异常代码,发现事务并没有回滚。

注释掉<!--此处配置使得事务控制 回滚失效 暂时注释掉-->下的内容,事务正常回滚。当时记得重复验证了要几次,事务并没有因为异常而回滚,所以才注释掉了下面的切面
但是后来不知道什么原因,放开这个注释事务也能正常回滚了。没有找到什么原因导致这样。(不知道是我当时测的时候的问题,还是后来因为改了什么东西的原因导致的,特意在此记录)。

package com.common.aspect;

import com.common.util.SensitiveParamUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

@Slf4j
public class Aspect {

    private final static SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public Object methodExecuteTime (ProceedingJoinPoint joinPoint) throws Throwable {
        Object object;
        Date startDate = new Date();
        Signature signature = joinPoint.getSignature();
        MethodSignature ms = (MethodSignature)signature;
        Method method = ms.getMethod();
        Class<?>[] paramTypes = method.getParameterTypes();
        Object[] args = joinPoint.getArgs();
        //访问目标方法的参数:
        log.info("{} 调用时间:{}",signature.toString(), sdf.format(startDate));
        long start = System.currentTimeMillis();
        object = joinPoint.proceed();
        long end = System.currentTimeMillis();
        String time = formatExecuteTime(end - start);
        log.info("{} 执行时间:{}",signature.toString(), time);
        new Thread(() -> {
            for (int i = 0; i < paramTypes.length; i++) {
                args[i] = SensitiveParamUtils.getJson(args[i]);
            }
            log.info("{} 方法入参{}", signature.toString(), Arrays.toString(args));
        }).start();

        return object;
    }

    private String formatExecuteTime(long executeTime) {
        long min = (executeTime % 3600000) / 60000;
        long sec = (executeTime % 60000) / 1000;
        long msec = executeTime % 10000;
        StringBuilder sb = new StringBuilder();
        if (min > 0) {
            sb.append(min).append("m ");
        }
        if (sec > 0) {
            sb.append(sec).append("s ");
        }
        sb.append(msec).append("ms");
        return sb.toString();
    }
}

单元测试、service自定义写,在service中加入空指针异常代码检测事务回滚的有效性。

猜你喜欢

转载自www.cnblogs.com/super-chao/p/11275454.html
今日推荐