spring aop相关注解

来源:互联网 发布:股东人数 软件 编辑:程序博客网 时间:2024/05/20 23:35

原博:点击打开链接

 如何用spring aop来实现日志管理的问题,现在个人觉得做日志管理最好的是Aop,当然有的人也喜欢用拦截器。

      Aop有的人说拦截不到Controller。有的人说想拦AnnotationMethodHandlerAdapter截到Controller必须得拦截org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter。首先Aop可以拦截到Controller的,这个是毋容置疑的;其次须拦截AnnotationMethodHandlerAdapter也不是必须的。Aop之所以有的人说拦截不到Controller是因为Controller被jdk代理了。我们只要把它交给cglib代理就可以了。


 

第一步:编写两个注解

1、拦截controller的注解

Java代码  收藏代码
  1. package com.ctlovedove.log.annotation;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Retention;  
  6. import java.lang.annotation.RetentionPolicy;  
  7. import java.lang.annotation.Target;  
  8. /** 
  9.  * 系统级别的controller层自定义注解 
  10.  * <br>拦截Controller 
  11.  * @author ct 
  12.  * 
  13.  */  
  14. @Target({ElementType.PARAMETER, ElementType.METHOD})//作用于参数或方法上  
  15. @Retention(RetentionPolicy.RUNTIME)  
  16. @Documented  
  17. public @interface SystemControllerLog {  
  18.     String description() default "";  
  19. }  

 2、拦截service的注解

Java代码  收藏代码
  1. package com.ctlovedove.log.annotation;  
  2.   
  3. import java.lang.annotation.Documented;  
  4. import java.lang.annotation.ElementType;  
  5. import java.lang.annotation.Retention;  
  6. import java.lang.annotation.RetentionPolicy;  
  7. import java.lang.annotation.Target;  
  8.   
  9. /** 
  10.  * 系统级别的service层自定义注解 
  11.  * <br>拦截service 
  12.  * @author ct 
  13.  */  
  14. @Target({ElementType.PARAMETER, ElementType.METHOD})//作用于参数或方法上  
  15. @Retention(RetentionPolicy.RUNTIME)  
  16. @Documented  
  17. public @interface SystemServiceLog {  
  18.     String description() default "";  
  19. }  

 

第二步:编写切点类

Java代码  收藏代码
  1. package com.ctlovedove.log.aspect;  
  2.   
  3. import java.lang.reflect.Method;  
  4. import java.util.Date;  
  5.   
  6. import javax.annotation.Resource;  
  7. import javax.servlet.http.HttpServletRequest;  
  8.   
  9. import org.apache.log4j.Logger;  
  10. import org.aspectj.lang.JoinPoint;  
  11. import org.aspectj.lang.annotation.AfterThrowing;  
  12. import org.aspectj.lang.annotation.Aspect;  
  13. import org.aspectj.lang.annotation.Before;  
  14. import org.aspectj.lang.annotation.Pointcut;  
  15. import org.json.JSONArray;  
  16. import org.springframework.stereotype.Component;  
  17. import org.springframework.web.context.request.RequestContextHolder;  
  18. import org.springframework.web.context.request.ServletRequestAttributes;  
  19.   
  20. import com.ctlovedove.joke.bean.Manager;  
  21. import com.ctlovedove.joke.bean.SystemLog;  
  22. import com.ctlovedove.joke.service.SystemLogService;  
  23. import com.ctlovedove.log.annotation.SystemControllerLog;  
  24. import com.ctlovedove.log.annotation.SystemServiceLog;  
  25. import com.ctlovedove.util.IpUtil;  
  26.   
  27. /** 
  28.  * 日志管理切点类 
  29.  * @author ct 
  30.  * 
  31.  */  
  32. @Aspect  
  33. @Component  
  34. public class SystemLogAspect {  
  35.     //注入Service用于把日志保存数据库   
  36.     @Resource  
  37.     private SystemLogService systemLogService;  
  38.     //本地异常日志记录对象    
  39.     private  static  final Logger logger = Logger.getLogger(SystemLogAspect.class);  
  40.       
  41.     //controller层切入点  
  42.     @Pointcut("@annotation(com.ctlovedove.log.annotation.SystemControllerLog)")  
  43.     public void controllerAspect() {  
  44.         System.out.println("========controllerAspect===========");  
  45.     }  
  46.     //service层切入点  
  47.     @Pointcut("@annotation(com.ctlovedove.log.annotation.SystemServiceLog)")  
  48.     public void serviceAspect() {  
  49.         System.out.println("========serviceAspect===========");  
  50.     }  
  51.       
  52.     /** 
  53.      * 前置通知 用于拦截Controller层操作  
  54.      * @param joinPoint 切点 
  55.      */  
  56.     @Before("controllerAspect()")  
  57.     public void doBefore(JoinPoint joinPoint) {  
  58.         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder  
  59.                 .getRequestAttributes()).getRequest();  
  60.         // 获取登陆用户信息  
  61.         Manager manager = (Manager) request.getSession().getAttribute(  
  62.                 "currentManager");  
  63.         // 获取请求ip  
  64.         String ip = IpUtil.getClientIp(request);  
  65.         try {  
  66.             // *========控制台输出=========*//  
  67.             System.out.println("=====前置通知开始=====");  
  68.             System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "."  
  69.                             + joinPoint.getSignature().getName() + "()"));  
  70.             System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));  
  71.             System.out.println("请求人:" + manager.getAccountName());  
  72.             System.out.println("请求IP:" + ip);  
  73.             // *========数据库日志=========*//  
  74.             SystemLog log = new SystemLog();  
  75.             log.setDescription(getControllerMethodDescription(joinPoint));  
  76.             log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
  77.             log.setType(0);  
  78.             log.setIp(ip);  
  79.             log.setExceptionCode(null);  
  80.             log.setExceptionDetail(null);  
  81.             log.setParams(null);  
  82.             log.setCreateUser(manager.getAccountName());  
  83.             log.setCreateDate(new Date());  
  84.             // 保存数据库  
  85.             systemLogService.save(log);  
  86.             System.out.println("=====前置通知结束=====");  
  87.         } catch (Exception e) {  
  88.             // 记录本地异常日志  
  89.             logger.error("==前置通知异常==");  
  90.             logger.error("异常信息:{}", e);  
  91.         }  
  92.     }  
  93.       
  94.     /** 
  95.      * 异常通知 用于拦截service层记录异常日志 
  96.      * @param joinPoint 
  97.      * @param e 
  98.      */  
  99.     @AfterThrowing(pointcut="serviceAspect()", throwing="e")  
  100.     public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {  
  101.         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder  
  102.                 .getRequestAttributes()).getRequest();  
  103.         // 获取登陆用户信息  
  104.         Manager manager = (Manager) request.getSession().getAttribute(  
  105.                 "currentManager");  
  106.         // 获取请求ip  
  107.         String ip = IpUtil.getClientIp(request);  
  108.         // 获取用户请求方法的参数并序列化为JSON格式字符串  
  109.         String params = "";  
  110.         Object[] args = joinPoint.getArgs();  
  111.         if (args != null) {  
  112.             JSONArray jsonArray = new JSONArray();  
  113.             jsonArray.put(args);  
  114.             params = jsonArray.toString();  
  115.         }  
  116.         try {  
  117.             /* ========控制台输出========= */  
  118.             System.out.println("=====异常通知开始=====");  
  119.             System.out.println("异常代码:" + e.getClass().getName());  
  120.             System.out.println("异常信息:" + e.getMessage());  
  121.             System.out.println("异常方法:"  
  122.                     + (joinPoint.getTarget().getClass().getName() + "."  
  123.                             + joinPoint.getSignature().getName() + "()"));  
  124.             System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));  
  125.             System.out.println("请求人:" + manager.getAccountName());  
  126.             System.out.println("请求IP:" + ip);  
  127.             System.out.println("请求参数:" + params);  
  128.             /* ==========数据库日志========= */  
  129.             SystemLog log = new SystemLog();  
  130.             log.setDescription(getServiceMthodDescription(joinPoint));  
  131.             log.setExceptionCode(e.getClass().getName());  
  132.             log.setType(1);  
  133.             log.setExceptionDetail(e.getMessage());  
  134.             log.setMethod((joinPoint.getTarget().getClass().getName() + "."  
  135.                     + joinPoint.getSignature().getName() + "()"));  
  136.             log.setParams(params);  
  137.             log.setCreateUser(manager.getAccountName());  
  138.             log.setCreateDate(new Date());  
  139.             log.setIp(ip);  
  140.             // 保存数据库  
  141.             systemLogService.save(log);  
  142.             System.out.println("=====异常通知结束=====");  
  143.         } catch (Exception ex) {  
  144.             // 记录本地异常日志  
  145.             logger.error("==异常通知异常==");  
  146.             logger.error("异常信息:{}", ex);  
  147.         }  
  148.   
  149.     }  
  150.   
  151.     /** 
  152.      * 获取注解中对方法的描述信息 用于Controller层注解  
  153.      * @param joinPoint 切点  
  154.      * @return 方法描述  
  155.      * @throws Exception  
  156.      */  
  157.     public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception{  
  158.         //获取目标类名  
  159.         String targetName = joinPoint.getTarget().getClass().getName();  
  160.         //获取方法名  
  161.         String methodName = joinPoint.getSignature().getName();  
  162.         //获取相关参数  
  163.         Object[] arguments = joinPoint.getArgs();  
  164.         //生成类对象  
  165.         Class targetClass = Class.forName(targetName);  
  166.         //获取该类中的方法  
  167.         Method[] methods = targetClass.getMethods();  
  168.           
  169.         String description = "";  
  170.           
  171.         for(Method method : methods) {  
  172.             if(!method.getName().equals(methodName)) {  
  173.                 continue;  
  174.             }  
  175.             Class[] clazzs = method.getParameterTypes();  
  176.             if(clazzs.length != arguments.length) {  
  177.                 continue;  
  178.             }  
  179.             description = method.getAnnotation(SystemControllerLog.class).description();  
  180.         }  
  181.         return description;  
  182.     }  
  183.       
  184.     /** 
  185.      * 获取注解中对方法的描述信息 用于service层注解 
  186.      * @param joinPoint 切点  
  187.      * @return 方法描述  
  188.      * @throws Exception  
  189.      */  
  190.     public static String getServiceMthodDescription(JoinPoint joinPoint) throws Exception{  
  191.         //获取目标类名  
  192.         String targetName = joinPoint.getTarget().getClass().getName();  
  193.         //获取方法名  
  194.         String methodName = joinPoint.getSignature().getName();  
  195.         //获取相关参数  
  196.         Object[] arguments = joinPoint.getArgs();  
  197.         //生成类对象  
  198.         Class targetClass = Class.forName(targetName);  
  199.         //获取该类中的方法  
  200.         Method[] methods = targetClass.getMethods();  
  201.           
  202.         String description = "";  
  203.           
  204.         for(Method method : methods) {  
  205.             if(!method.getName().equals(methodName)) {  
  206.                 continue;  
  207.             }  
  208.             Class[] clazzs = method.getParameterTypes();  
  209.             if(clazzs.length != arguments.length) {  
  210.                 continue;  
  211.             }  
  212.             description = method.getAnnotation(SystemServiceLog.class).description();  
  213.         }  
  214.         return description;  
  215.     }  
  216. }  

 

第三步:将controller的代理权交给cglib。那么此时需要在spring的配置文件中添加如下代码:

Xml代码  收藏代码
  1. <!--启动对@AspectJ注解的支持 , proxy-target-class设置为true表示通知spring使用cglib而不是jdk的来生成代理方法,这样AOP可以拦截到Controller -->  
  2. <aop:aspectj-autoproxy proxy-target-class="true" />  

 切记,如果你使用的是spring mvc的话,这句一定要写在springmvc的配置文件中,否则会似的@AspectJ不起作用的,我是深受其害的一位。

 

第四步:开始使用注解

在controller或service的方法上添加注解,示例如下:

Java代码  收藏代码
  1. @RequestMapping("save")  
  2. @SystemControllerLog(description="新增笑话")  
  3. public String save(JokeInfo jokeInfo, RedirectAttributes attributes, HttpServletRequest request, HttpSession session){  
  4.     logger.info("新增笑话--jokeinfo--"+jokeInfo);  
  5.     try {  
  6.         if(jokeInfo == null){  
  7.             attributes.addFlashAttribute("errorMsg""新增笑话失败");  
  8.             return "redirect:list.do";  
  9.         }  
  10.         if(StringUtil.isNull(jokeInfo.getSource())){  
  11.             jokeInfo.setSource(session.getAttribute("currentManager")+"");  
  12.         }  
  13.         jokeInfo.setSourceIp(IpUtil.getClientIp(request));  
  14.         jokeInfo.setPubDate(new Date());  
  15.         jokeInfoService.save(jokeInfo);  
  16.         attributes.addFlashAttribute("errorMsg""新增成功");  
  17.     } catch (Exception e) {  
  18.         logger.error("保存新笑话失败", e);  
  19.         attributes.addFlashAttribute("errorMsg""新增笑话失败");  
  20.     }  
  21.     return "redirect:list.do";  
  22. }  

 

最终效果可见下面截图:



 如果操作顺利的话,以上便是完整的步骤了。但是在我的编写与测试过程中,遇到了好多问题,例如:

 

问题1:在启动tomcat的时候,报org.xml.sax.SAXParseException; lineNumber: 23; columnNumber: 53; 元素 "aop:aspectj-autoproxy" 的前缀 "aop" 未绑定

 

通过查询文档发现,在springmvc配置文件中,我们不仅仅要引入Aop的名称空间,还要在xsi:schemaLocation中加入aop的xsd文件 。

 

问题2:AspectJ 出现错误::0 can't find referenced pointcut

原因是我用的jdk7与aspectjrt.jar包不兼容,解决方法是更换jar包。

当环境为:

jdk 1.7, spring version is 3.0+, 如果使用aspectjrt-1.6.2 and aspectjweaver-1.6.2这个版本,就会出现上述错误,将aspectj and aspectjweaver 版本改为1.7.3 or more,问题得到解决。

 

补充:上面是基于注解的方式进行的aop配置,但有些朋友更喜欢使用xml配置文件的方式,比如我,所以下面是部分xml的配置,如有问题,还请大神们指教。

1、首先,将切面类中的SystemLogAspect中的注解去掉。

Java代码  收藏代码
  1. package com.ctlovedove.log.aspect;  
  2.   
  3. import java.lang.reflect.Method;  
  4. import java.util.Date;  
  5.   
  6. import javax.annotation.Resource;  
  7. import javax.servlet.http.HttpServletRequest;  
  8.   
  9. import org.apache.log4j.Logger;  
  10. import org.aspectj.lang.JoinPoint;  
  11. import org.aspectj.lang.annotation.AfterThrowing;  
  12. import org.aspectj.lang.annotation.Before;  
  13. import org.aspectj.lang.annotation.Pointcut;  
  14. import org.json.JSONArray;  
  15. import org.springframework.web.context.request.RequestContextHolder;  
  16. import org.springframework.web.context.request.ServletRequestAttributes;  
  17.   
  18. import com.ctlovedove.joke.bean.Manager;  
  19. import com.ctlovedove.joke.bean.SystemLog;  
  20. import com.ctlovedove.joke.service.SystemLogService;  
  21. import com.ctlovedove.log.annotation.SystemControllerLog;  
  22. import com.ctlovedove.log.annotation.SystemServiceLog;  
  23. import com.ctlovedove.util.IpUtil;  
  24.   
  25. /** 
  26.  * 日志管理切点类 
  27.  * @author chenting 
  28.  * 
  29.  */  
  30. public class SystemLogAspect {  
  31.     //注入Service用于把日志保存数据库   
  32.     @Resource  
  33.     private SystemLogService systemLogService;  
  34.     //本地异常日志记录对象    
  35.     private  static  final Logger logger = Logger.getLogger(SystemLogAspect.class);  
  36.       
  37.      
  38.     /** 
  39.      * 前置通知 用于拦截Controller层操作  
  40.      * @param joinPoint 切点 
  41.      */  
  42.     public void doBefore(JoinPoint joinPoint) {  
  43.         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder  
  44.                 .getRequestAttributes()).getRequest();  
  45.         // 获取登陆用户信息  
  46.         Manager manager = (Manager) request.getSession().getAttribute(  
  47.                 "currentManager");  
  48.         // 获取请求ip  
  49.         String ip = IpUtil.getClientIp(request);  
  50.         try {  
  51.             // *========控制台输出=========*//  
  52.             System.out.println("=====前置通知开始=====");  
  53.             System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "."  
  54.                             + joinPoint.getSignature().getName() + "()"));  
  55.             System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));  
  56.             System.out.println("请求人:" + manager.getAccountName());  
  57.             System.out.println("请求IP:" + ip);  
  58.             // *========数据库日志=========*//  
  59.             SystemLog log = new SystemLog();  
  60.             log.setDescription(getControllerMethodDescription(joinPoint));  
  61.             log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
  62.             log.setType(0);  
  63.             log.setIp(ip);  
  64.             log.setExceptionCode(null);  
  65.             log.setExceptionDetail(null);  
  66.             log.setParams(null);  
  67.             log.setCreateUser(manager.getAccountName());  
  68.             log.setCreateDate(new Date());  
  69.             // 保存数据库  
  70.             systemLogService.save(log);  
  71.             System.out.println("=====前置通知结束=====");  
  72.         } catch (Exception e) {  
  73.             // 记录本地异常日志  
  74.             logger.error("==前置通知异常==");  
  75.             logger.error("异常信息:{}", e);  
  76.         }  
  77.     }  
  78.       
  79.     /** 
  80.      * 异常通知 用于拦截service层记录异常日志 
  81.      * @param joinPoint 
  82.      * @param e 
  83.      */  
  84.     public void doAfterThrowing(JoinPoint joinPoint, Throwable e) {  
  85.         HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder  
  86.                 .getRequestAttributes()).getRequest();  
  87.         // 获取登陆用户信息  
  88.         Manager manager = (Manager) request.getSession().getAttribute(  
  89.                 "currentManager");  
  90.         // 获取请求ip  
  91.         String ip = IpUtil.getClientIp(request);  
  92.         // 获取用户请求方法的参数并序列化为JSON格式字符串  
  93.         String params = "";  
  94.         Object[] args = joinPoint.getArgs();  
  95.         if (args != null) {  
  96.             JSONArray jsonArray = new JSONArray();  
  97.             jsonArray.put(args);  
  98.             params = jsonArray.toString();  
  99.         }  
  100.         try {  
  101.             /* ========控制台输出========= */  
  102.             System.out.println("=====异常通知开始=====");  
  103.             System.out.println("异常代码:" + e.getClass().getName());  
  104.             System.out.println("异常信息:" + e.getMessage());  
  105.             System.out.println("异常方法:"  
  106.                     + (joinPoint.getTarget().getClass().getName() + "."  
  107.                             + joinPoint.getSignature().getName() + "()"));  
  108.             System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));  
  109.             System.out.println("请求人:" + manager.getAccountName());  
  110.             System.out.println("请求IP:" + ip);  
  111.             System.out.println("请求参数:" + params);  
  112.             /* ==========数据库日志========= */  
  113.             SystemLog log = new SystemLog();  
  114.             log.setDescription(getServiceMthodDescription(joinPoint));  
  115.             log.setExceptionCode(e.getClass().getName());  
  116.             log.setType(1);  
  117.             log.setExceptionDetail(e.getMessage());  
  118.             log.setMethod((joinPoint.getTarget().getClass().getName() + "."  
  119.                     + joinPoint.getSignature().getName() + "()"));  
  120.             log.setParams(params);  
  121.             log.setCreateUser(manager.getAccountName());  
  122.             log.setCreateDate(new Date());  
  123.             log.setIp(ip);  
  124.             // 保存数据库  
  125.             systemLogService.save(log);  
  126.             System.out.println("=====异常通知结束=====");  
  127.         } catch (Exception ex) {  
  128.             // 记录本地异常日志  
  129.             logger.error("==异常通知异常==");  
  130.             logger.error("异常信息:{}", ex);  
  131.         }  
  132.   
  133.     }  
  134.   
  135.     /** 
  136.      * 获取注解中对方法的描述信息 用于Controller层注解  
  137.      * @param joinPoint 切点  
  138.      * @return 方法描述  
  139.      * @throws Exception  
  140.      */  
  141.     public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception{  
  142.         //获取目标类名  
  143.         String targetName = joinPoint.getTarget().getClass().getName();  
  144.         //获取方法名  
  145.         String methodName = joinPoint.getSignature().getName();  
  146.         //获取相关参数  
  147.         Object[] arguments = joinPoint.getArgs();  
  148.         //生成类对象  
  149.         Class targetClass = Class.forName(targetName);  
  150.         //获取该类中的方法  
  151.         Method[] methods = targetClass.getMethods();  
  152.           
  153.         String description = "";  
  154.           
  155.         for(Method method : methods) {  
  156.             if(!method.getName().equals(methodName)) {  
  157.                 continue;  
  158.             }  
  159.             Class[] clazzs = method.getParameterTypes();  
  160.             if(clazzs.length != arguments.length) {//比较方法中参数个数与从切点中获取的参数个数是否相同,原因是方法可以重载哦  
  161.                 continue;  
  162.             }  
  163.             description = method.getAnnotation(SystemControllerLog.class).description();  
  164.         }  
  165.         return description;  
  166.     }  
  167.       
  168.     /** 
  169.      * 获取注解中对方法的描述信息 用于service层注解 
  170.      * @param joinPoint 切点  
  171.      * @return 方法描述  
  172.      * @throws Exception  
  173.      */  
  174.     public static String getServiceMthodDescription(JoinPoint joinPoint) throws Exception{  
  175.         //获取目标类名  
  176.         String targetName = joinPoint.getTarget().getClass().getName();  
  177.         //获取方法名  
  178.         String methodName = joinPoint.getSignature().getName();  
  179.         //获取相关参数  
  180.         Object[] arguments = joinPoint.getArgs();  
  181.         //生成类对象  
  182.         Class targetClass = Class.forName(targetName);  
  183.         //获取该类中的方法  
  184.         Method[] methods = targetClass.getMethods();  
  185.           
  186.         String description = "";  
  187.           
  188.         for(Method method : methods) {  
  189.             if(!method.getName().equals(methodName)) {  
  190.                 continue;  
  191.             }  
  192.             Class[] clazzs = method.getParameterTypes();  
  193.             if(clazzs.length != arguments.length) {//比较方法中参数个数与从切点中获取的参数个数是否相同,原因是方法可以重载哦  
  194.                 continue;  
  195.             }  
  196.             description = method.getAnnotation(SystemServiceLog.class).description();  
  197.         }  
  198.         return description;  
  199.     }  
  200. }  

 2、xml配置文件代码如下(该配置仍然要方在springmvc的配置文件中,因为仍然有部分使用了注解)

Xml代码  收藏代码
  1. <!-- 系统操作日志配置  start -->  
  2.     <!-- 声明切面类 -->  
  3.     <bean id="SystemLogAspect" class="com.ctlovedove.log.aspect.SystemLogAspect"></bean>  
  4.     <aop:config>  
  5.         <!-- 声明切面 -->  
  6.         <aop:aspect ref="SystemLogAspect">  
  7.             <!--   
  8.                 1、pointcut="@annotation(com.ctlovedove.log.annotation.SystemControllerLog)" 表示切入点是注解   
  9.                 2、method 指向的方法,是切面类中的方法,表示当程序触发pointcut指向的注解时,aop会启动method方法  
  10.             -->  
  11.             <aop:before method="doBefore" pointcut="@annotation(com.ctlovedove.log.annotation.SystemControllerLog)"/>  
  12.             <!-- <aop:after method="doAfterThrowing" pointcut="@annotation(com.ctlovedove.log.annotation.SystemServiceLog)"/> -->  
  13.             <aop:after-throwing method="doAfterThrowing" pointcut="@annotation(com.ctlovedove.log.annotation.SystemServiceLog)" throwing="e"/>  
  14.         </aop:aspect>  
  15.     </aop:config>  
  16.     <!-- 系统操作日志配置  end -->  
原创粉丝点击