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中加入空指针异常代码检测事务回滚的有效性。