上一篇Spring AOP项目应用——方法入参校验 & 日志横切 介绍了 spring AOP 5切面类型及应用场景。本次结合注解使用,方便又实惠。实现如下:
封装日志切面
@Aspect
@Component
public class LogAspect {
private static ILog logger = LogFactory.getLogger(LogAspect.class);
@Around("execution(* com.component..*.*(..)) && @annotation(com.aspect.Log)")
public Object around(ProceedingJoinPoint point) throws Throwable {
Long startTime=System.currentTimeMillis();
String methodName=point.getSignature().getName();
Object[] args=point.getArgs();
String[] paramNames = ((CodeSignature) point.getSignature()).getParameterNames();
try {
logger.info("[ACCESS] {}: args:{}", methodName, JSON.toJSONString(args));
Object resultValue = point.proceed();
logger.info("[END] {}: result:{} {}ms ", methodName, JSON.toJSONString(args), System.currentTimeMillis() - startTime);
return resultValue;
} catch (Exception e) {
logger.error("", e);
}
return null;
}
}
定义切面注解类
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Log {
}
调用处
@Log
public Result<UserDto> createTrade(UserDto UserDto) {
if (UserDto == null || UserDto.getOrderId() == null || UserDto.getBusinessId() == null) {
return ResultWrapper.fail(ErrorCode.PARAMETER_CANNOT_NULL);
}
String lockKey = Constants.USER_KEY_PREFIX + UserDto.getOrderId();
return new SimpleRedisLock().execute(lockKey, Constants.DEFAULT_LOCK_TIMEOUT, () -> {
Result<UserDto> result = tradeService.createTrade(UserDto);
return result;
});
}
Last but not least :添加aop配置生效
<aop:aspectj-autoproxy proxy-target-class="true"/>
执行效果:方法入参、返回结果日志如下
另外我在考虑一点,并发情况下,会不会导致日志打串了。比如方法1的入参print完还没print result,方法2就又把入参print出来了。导致同一方法日志不连续,不便排查线上问题。
答案:当然不会。因为。。。spring bean 是默认单例管理哒!无状态bean(AOP 切面类也在context容器中管理)