Spring Aop 实现日志记录

最近一段时间做项目总是用到AOP,在此做个简单的Spring Aop  日志记录Demo

简单的回顾一下Aop,他的代理方式有两种:

第一种:.静态代理(也就是编译时进行代理,如AspectJ)。

第二种:动态代理(动态又分为两种代理方式1.JDK动态代理 2.CGLIB动态代理,至于区别就不多说了)。

想要实现多个方法用同一个切面增强,怎么区别方法的模块名字和描述呢?当然方式很多,我这里用自定义

注解来实现:

第一步编写自定义注解:

---------自定义注解参数解释:

  1. /** 
  2.  * 表示对标记有xxx注解的类,做代理 注解@Retention可以用来修饰注解,是注解的注解,称为元注解。 
  3.  * Retention注解有一个属性value,是RetentionPolicy类型的,Enum RetentionPolicy是一个枚举类型, 
  4.  * 这个枚举决定了Retention注解应该如何去保持,也可理解为Rentention 搭配 
  5.  * RententionPolicy使用。RetentionPolicy有3个值:CLASS RUNTIME SOURCE 
  6.  * 用@Retention(RetentionPolicy 
  7.  * .CLASS)修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,但不会被虚拟机读取在运行的时候; 
  8.  * 用@Retention(RetentionPolicy.SOURCE 
  9.  * )修饰的注解,表示注解的信息会被编译器抛弃,不会留在class文件中,注解的信息只会留在源文件中; 
  10.  * 用@Retention(RetentionPolicy.RUNTIME 
  11.  * )修饰的注解,表示注解的信息被保留在class文件(字节码文件)中当程序编译时,会被虚拟机保留在运行时, 
  12.  * 所以他们可以用反射的方式读取。RetentionPolicy.RUNTIME 
  13.  * 可以让你从JVM中读取Annotation注解的信息,以便在分析程序的时候使用. 
  14.  *  
  15.  * 类和方法的annotation缺省情况下是不出现在javadoc中的,为了加入这个性质我们用@Documented 
  16.  *  java用  @interface Annotation{ } 定义一个注解 @Annotation,一个注解是一个类。 
  17.  *  @interface是一个关键字,在设计annotations的时候必须把一个类型定义为@interface,而不能用class或interface关键字  
Java代码   收藏代码
  1. @Target({ElementType. METHOD})  
  2. @Retention(RetentionPolicy.RUNTIME )  
  3. @Documented  
  4. public @interface MethodRecordLog {  
  5.         
  6.       String moduleName(); //模块名称  
  7.       String logType(); //日志类别  
  8.       String desc() default "描述信息" ;// 模块描述
  9. }  

第二步编写日志记录类(也就是增强类)

Java代码   收藏代码
  1.     @Aspect  
  2.     @Component  
  3.     public class LogAspect {  
  4.        
  5.      @Autowired  
  6.      private LogService LogService;  
  7.        
  8.      //此注解是后置增强,方法执行成功后会执行  
  9.    @AfterReturning("within(com.xxx.*.web..*) && @annotation(mrl)")   
  10.    public void insertLogSuccess(final ProceedingJoinPoint pjp, final MethodRecordLog mrl){   
  11.      String moduleName = mrl.moduleName() ;  
  12.      String methodName = jp.getSignature().getName(); //获取目标方法名  
  13.         
  14.        XXLog xxLog = new XXLog(); 
  15.             xxLog.setXX(XX);//这里设置属性就不多写了
  16.             LogService.saveLog(xxLog);//调用方法持久DB
  17.    }   
  18.   
  19.    //该方法体为异常通知,当目标方法出现异常时,执行该方法体   
  20.    @AfterThrowing(pointcut= "within(com.xxx.*.web..*) && @annotation(mrl)", throwing="ex")   
  21.    public void insertLog(final ProceedingJoinPoint pjp, final MethodRecordLog mrl, CRUDException ex){   
  22.      String moduleName = mrl.moduleName() ;  
  23.      String methodName = jp.getSignature().getName(); //获取目标方法名  
  24.         
  25.        XXLog xxLog = new XXLog(); 
  26.             xxLog.setXX(XX);//这里设置属性就不多写了
  27.             LogService.saveLog(xxLog);//调用方法持久DB
  28.    }  
  29.     
  30. //ProceedingJoinPoint继承自JoinPoint,在 JoinPoint的基础上添加了反射、具体参照javadoc
    
注:@AfterReturning为注解方法体成功执行后,执行的方法。@AfterThrowing为注解方法体抛出CRUDException 异常时执行的方法。ProceedingJoinPoint pjp参数可以获得注解方法体的相关值,包括类名、方法名、参数等信息。MethodRecordLog mrl参数为自定义注解的类,可以获得自定义注解的值

第三步在spring 的配置文件里面启动注解:

Java代码   收藏代码
  1. <!-- 启用@AspectJ支持 -->  
  2.        <aop:aspectj-autoproxy />  

第四步是controller层面自定义注解的用法:

Java代码  
  1.       @JpfLog(moduleName="用户",logType="",desc= "添加用户")  
  2.       @RequestMapping(value = "/saveByUser")  
  3.       public String saveByUser(User user) throws CRUDException {  
  4.              int result = userService.saveUser(user);  
  5.              return "";  
  6.       }  

猜你喜欢

转载自songshidong.iteye.com/blog/2101408