Spring AOP对日志记录、Exception日志记录等等

 本文来自 http://www.javaeye.com/topic/71996
本人感觉还是很有借鉴意义,所以在此贴出,加以评论!
原文如下:
---------------------------------------------------------------------
利用spring aop对日志进行管理,还是采用对比的方式进行,

修改前:

偶们的做法是在action里记录日志,注意这个日志是面向用户的日志,姑且称它为业务日志,至于后台日志,则在此文章中暂不考虑,基本是通过log4j打印到后台日志文件中。看下面一段代码:


    1 .   try   {   
   
2.     employeInfoManageService.saveEmploye(vo, authForm.getLoginName());   
   
3.   
   
4.     LogVO logVO = new LogVO(Constants.LOG_LEVEL_INFO,   
   
5.                 Constants.LOG_TYPE_BACK, "用户:" + authForm.getLoginName()   
   
6.                             + "增加员工成功!");   
   
7.     logService.saveLog(logVO);   
   
8. }
  catch  (Exception e)  {   
   
9.     log.error(e);   
  
10.     LogVO logVO = new LogVO(Constants.LOG_LEVEL_ERROR,   
  
11.             Constants.LOG_TYPE_BACK, "用户:" + authForm.getLoginName()   
  
12.                             + "增加员工失败!");   
  
13.     try {   
  
14.         logService.saveLog(logVO);   
  
15.     }
 catch (Exception e1) {   
  
16.         log.error(e1);     
  
17.     return messageForward("error""alert.db.exception",      
  
18.                     new Object[] {});   }
   
  
19. }
  

 

这段代码实际上已经将写日志的过程封装起来,开发者只需要传入3个参数:操作者、是前台系统还是后台系统、以及日志的错误等级,其它的如操作者机器IP, 日志时间等信息由系统统一设定,即使是这样,如果一个action里面有多个操作,代码看起来也非常臃肿,而且给开发者增加了工作量,既然有了aop,为 什么不利用一下?看下面改造的代码:

    1 .  LogVO logVO  =   new  LogVO(Constants.LOG_LEVEL_INFO,   
   
2 .                 Constants.LOG_TYPE_BACK,  " 用户: "   +  authForm.getLoginName()   
   
3 .                              +   " 增加员工 " );   
   
4 try   {   
   
5.     employeInfoManageService.saveEmploye(vo, authForm.getLoginName(), logVO);   
   
6. }
  catch  (Exception e)  {   
   
7.     log.error(e);   
   
8.     return messageForward("error""alert.db.exception",   
   
9.                     new Object[] {});   
  
10. }
  
既然是应用到aop,当然少不了aop的配置了,看下面的配置代码:

 

   1.   < aop:config >   
   2.     
< aop:advisor  pointcut ="execution(* *..*Service.*(..))"  advice-ref ="txAdvice" />   
     3.     
< aop:advisor  pointcut ="execution(* *..*Service.save*(..)) || execution(* *..*Service.update*(..)) || execution(* *..*Service.delete*(..))"  advice-ref ="logAfterAdvice" />   
   4. 
</ aop:config >   
   5.   
   6. 
< bean  id ="logAfterAdvice"  class ="com.fudannet.framework.aop.LogAfterAdvice" />   
噢,aop:config的第一行是不是很熟悉啊,对,就是我们前面所配置的事务管理,这里,应该很清楚采用统一的aop配置的好处了吧。下面贴出logAfterAdvice的代码:

 

    1 .   public   void  afterReturning(Object returnObj, Method method, Object[] args,   
   
2 .             Object targetObj)  throws  Throwable  {   
   
3.     if(method.getName().equals("saveLog")) return;   
   
4.     for(int i = 0; i < args.length; i++){   
   
5.         if(args[i] instanceof LogVO){   
   
6.             log.info("开始写入日志......");   
   
7.             writeLog((LogVO)args[i]);   
   
8.         }
   
   
9.     }
   
  
10. }
   
  
11 .   
  
12 private   void  writeLog(LogVO vo) {   
  
13.     try {   
  
14.         vo.setDescription(vo.getDescription() + "成功!");   
  
15.         logService.saveLog(vo);   
  
16.     }
 catch (RuntimeException e) {   
  
17.         log.error(e);   
  
18. }
   
  
19.   
  
20public void setLogService(LogService logService) {   
  
21.     this.logService = logService;   
  
22. }
  

 

这段代码应该很清楚了,将logService注入到拦截log的advice里,进行正确操作的日志记录,而afterReturning方法里 的第一行判断是由于logService里的写日志的方法是以save开始的。所以,如果拦截器拦截到此方法,不需要记录日志。

正确的日志记录完,当然如果发生异常,我们需要记录操作的失败日志,当然了,我们也是通过aop来做,但是这次是通过实现exception advice来实现,代码如下:

    1 .   public   void  afterThrowing(Method method,Object[] args,Object target,Exception e)  throws  Throwable  {   
   
2.     if(method.getName().equals("saveLog")) return;   
   
3.     for(int i = 0; i < args.length; i++){   
   
4.         if(args[i] instanceof LogVO){   
   
5.             log.info开始写入日志......");  
   6.             writeLog((LogVO)args[i]);  
   
7.         }
  
   
8.     }
  
   
9. }
  
  
10 .  
  
11 private   void  writeLog(LogVO vo) {  
  
12.     try {  
  
13.         vo.setDescription(vo.getDescription() + "失败!");   
  
14.         logThrowService.saveLog(vo);   
  
15.     }
 catch (RuntimeException e) {   
  
16.         log.error(e);   
  
17.     }
   
  
18. }
   
  
19 .   
  
20 public   void  setLogThrowService(LogService logThrowService)  {   
  
21.     this.logThrowService = logThrowService;   
  
22. }
  

上面代码已经很好的说明了,如果发生exception的话,日志是怎么记录的,这里要提到的一点的是,异常的处理稍微有一些复杂,就拿本例的代码能看出 来,只要在service层有异常的时候,都会记录失败日志,实际上,很多时候,未必是这样,在某个模块,可能需要定义一种特殊的异常,而一旦这种异常发 生,则需要进入另外一个流程或者做一些特殊的处理,这个时候需要根据具体情况做一些变更,比如在上面代码我们加上:
    1 .   public   void  afterThrowing(Method method,Object[] args,Object target,OrderException e)  throws  Throwable  {   
   
2.     log.info("......");   
   
3.     //do something   
   4. }
  
则如果OrderException被抛出,就会到此方法中执行,而不会去写日志。
--------------------------------------------------------------------------------
其中的封装方式虽然一般,但是还是比较好的解决了问题!对于 LogVO类我们可以把他继续扩展下去,比如设定访问用户,IP,seq文等.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值