SpringAOP实现自动生成日志

         项目中总要发布一下服务供系统内外调用,为了方便排查错误,入参出参都要以日志的形式记录下来。 
传统做法:缺点一目了然,参数少的时候只能说还好,参数一多,烦不胜烦,浪费时间。
 
Java代码 
  1. private static final Logger logger = Logger.getLogger(HelloServiceImpl.class);  
  2. public String sayHello(String name,String words) {  
  3.       logger.info("remote input:name="+name+",words="+words);  
  4.       //业务逻辑  
  5.       String result = "Hello"+name+","+words);  
  6.       logger.info("remote output:result="+result);  
  7.       return result;  
  8. }  
         于是基于java.lang.annotation,借鉴AOP的思想,将日志功能做成一个切面,横向切入到业务逻辑前后(方法开始前和结束后)。 
        由于java的反射是不能获取方法的参数名的,网上有一个第三方工具包JAVAssist提供了现成的方法,但笔者觉得挺麻烦的,决定使用约定优于配置的方式来获取方法的参数名。大家大概猜到是什么了吧?对!就是建一个自定义注解。
 
Java代码 
  1. @Target (ElementType.METHOD)    
  2. @Retention(RetentionPolicy.RUNTIME)    
  3. @Documented    
  4. public @interface  AOPLog4jAnnotation {  
  5.     String paramCollection();  
  6. }  

在需要日志切面的地方(方法)加上这个注解。  
Java代码 
  1. public class HelloServiceImpl implements HelloService{  
  2.     @Override  
  3.     @AOPLog4jAnnotation(paramCollection="name,words")  
  4.     public String sayHello(String name,String words) {  
  5.         String text = "Hello "+name+"!"+words+".";  
  6.         return text;  
  7.     }  
  8. }  

         大家也看到了,笔者的这种方式的明显的缺点:需要按一定规则(把参数按顺序填进去,并用英文逗号隔开)把方法参数名配置在注解中。  
Java代码 
  1. @AOPLog4jAnnotation(paramCollection="name,words")  

唯一的好处是...只需要复制上面这行,然后遵循规则填写参数名。 
唯二的好处是...日志格式统一。 
完了,伤心了,感觉实用性不强,哎。  
算了,把代码都贴上吧,留着以后改进。 
Spring配置:
 
Java代码 
  1. <bean id="helloService" class="com.aop.log4j.service.impl.HelloServiceImpl" />  
  2. <bean id="aspect" class="com.aop.log4j.aspect.HelloAspect"/>  
  3. <aop:config>  
  4.     <aop:pointcut id="pointcut" expression="execution(* com.aop.log4j.service.HelloService.*(..)))" />  
  5.     <aop:aspect ref="aspect">  
  6.         <aop:around pointcut-ref="pointcut" method="arround"/>  
  7.     </aop:aspect>  
  8. </aop:config>  
切面代码:  
Java代码 
  1. public class HelloAspect {  
  2.     private static final Logger logger = Logger.getLogger(HelloAspect.class);  
  3.     private static final String DOT = ".";//点号  
  4.     private static final String COMMA = ",";//逗号  
  5.       
  6.     public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {  
  7.         StringBuilder sb = new StringBuilder();  
  8.         Object[] paramValues = joinPoint.getArgs();//获取参数值  
  9.         String[] paramNames = new String[paramValues.length];  
  10.         Class<? extends Object> invokeClass = joinPoint.getTarget().getClass();  
  11.         String signatureName = joinPoint.getSignature().getName();  
  12.         Method methods[] = invokeClass.getMethods();  
  13.         for (Method method : methods) {  
  14.         if(method.getName().equals(signatureName)) {  
  15.                 String paramCollection = method.getAnnotation  
  16.                       (AOPLog4jAnnotation.class).paramCollection();//获取注解值  
  17.                 String[] names = paramCollection.split(COMMA);  
  18.                 System.arraycopy(names, 0, paramNames, 0, names.length);  
  19.             }  
  20.         }  
  21.         for (int i = 0; i < paramValues.length; i++) {  
  22.             sb.append(paramNames[i] + "=" + paramValues[i] + COMMA);  
  23.         }  
  24.         //入参日志  
  25.         logger.info(invokeClass  + DOT + signatureName + ",remote input:"   
  26.                         + sb.toString().substring(0, sb.length() - 1));  
  27.         try {  
  28.            Object result = joinPoint.proceed();  
  29.            //出参日志  
  30.            logger.info(invokeClass  + DOT + signatureName   
  31.                    + ",remote output:" + result);  
  32.            return result;  
  33.         } catch (Exception e) {  
  34.            logger.error(invokeClass  + DOT + signatureName  
  35.                    + " invoke error");  
  36.         }  
  37.         return null;  
  38.     }  
  39. }  
调用HelloService服务,输出:  

Java代码 
  1. [INFO] 2012-10-03 11:54:29,807 [com.aop.log4j.aspect.HelloAspect.arround] - class com.aop.log4j.service.impl.HelloServiceImpl.sayHello,remote input:name=Java,words=I love you.  
  2. [INFO] 2012-10-03 11:54:29,808 [com.aop.log4j.aspect.HelloAspect.arround] - class com.aop.log4j.service.impl.HelloServiceImpl.sayHello,remote output:Hello Java!I love you.  

oschina好像不能插入附件,请移步去我的iteye博客下载吧,谢谢。

http://dl.iteye.com/topics/download/0e1af44b-81d0-351c-badb-5e758093767b

你可能感兴趣的:(spring,AOP,log4j,annotationjava)