1 发现问题
项目配置了 Spring AOP,但会被调用两次:
开始
before()
[2017-07-26 11:10:18.071] [INFO]:[com.deniro.jail.service.sys.SysLogAspect][log] [com.deniro.jail.service.sys.SysLogAspect.log(SysLogAspect.java:43)] [调用方法:void com.deniro.jail.service.biz.DictItemService.save(DictItem);输入参数:[com.deniro.jail.domain.biz.DictItem@4f55a864[dictItemId=<null>,dictItemType=health,dictItemDescription=1,dictItemValue=1,dictItemIsOptional=true,createTime=2017-07-26 11:10:18.056,modifyTime=2017-07-26 11:10:18.056]]]
开始
before()
Hibernate: insert into ...
结束
[2017-07-26 11:10:18.141] [INFO]:[com.deniro.jail.service.sys.SysLogAspect][log] [com.deniro.jail.service.sys.SysLogAspect.log(SysLogAspect.java:58)] [输出参数:null;耗时:0:00:00.062]
结束
2 分析问题
切面定义如下:
@Component
@Aspect
public class SysLogAspect {
static Logger logger = LoggerFactory.getLogger(SysLogAspect.class);
@Pointcut("@annotation(com.deniro.jail.domain.sys.SysLog)")
private void sysLog() {
}
/**
* 记录日志
*
* @param pjp
*/
@Around("sysLog()")
public Object log(ProceedingJoinPoint pjp) {
logger.info("调用方法:{};输入参数:{}", pjp.getSignature()
, pjp
.getArgs());
StopWatch sw = new StopWatch();
sw.start();
Object o = null;
try {
System.out.println("开始");
o = pjp.proceed();
System.out.println("结束");
} catch (Throwable throwable) {
logger.error("记录日志", throwable);
}
sw.stop();
logger.info("输出参数:{};耗时:{}", o, sw.toString());
return o;
}
}
切点用的是注解配置方式,查了一下,只在一个地方定义了这个注解:
@RequestMapping(value = "/save")
@ResponseBody
@SysLog(description = " 保存【字典项】")
public AjaxResponse save(DictItem dictItem) {
try {
dictitemService.save(dictItem);
return AjaxResponse.success();
} catch (Exception e) {
return AjaxResponse.fail();
}
}
怀疑是重复定义的问题,我们找找看。
打开 spring 的 MVC 配置文件:
<!-- 开启对 @Aspect 的支持-->
<aop:aspectj-autoproxy/>
这是第一处定义的地方,如果类配置了 @Aspect,那么这个类会被自动扫描到 spring 框架中。
第二处定义的地方在 spring 框架配置文件:
<!-- 系统日志切面-->
<bean class="com.deniro.jail.service.sys.SysLogAspect"/>
难怪被执行了两次呢O(∩_∩)O~
3 解决问题
删除 spring 框架配置文件中定义的切面 bean,好了,现在一切恢复正常咯O(∩_∩)O~
记住:开启了 @Aspect 配置,而且切面类加了 @Aspect 注解,这时就不需要再对切面类进行配置 XML 配置哦。