SpringAOP实现自动生成日志 【基于java.lang.annotation约定】

标签: springaop 日志 java | 发表时间:2012-10-03 12:33 | 作者:
出处:http://www.iteye.com
           项目中总要发布一下服务供系统内外调用,为了方便排查错误,入参出参都要以日志的形式记录下来。
传统做法:缺点一目了然,参数少的时候只能说还好,参数一多,烦不胜烦,浪费时间。
    private static final Logger logger = Logger.getLogger(HelloServiceImpl.class);
    public String sayHello(String name,String words) {
          logger.info("remote input:name="+name+",words="+words);
          //业务逻辑
          String result = "Hello"+name+","+words);
          logger.info("remote output:result="+result);
          return result;
    }

           于是借鉴了AOP的思想,将日志功能做成一个切面,横向切入到业务逻辑前后(方法开始前和结束后)。
        另外,解释一下什么是【基于java.lang.annotation约定】。
        由于java的反射是不能获取方法的参数名的,网上有一个第三方工具包JAVAssist提供了现成的方法,但笔者觉得没必要引入第三方jar,决定使用约定优于配置的方式来获取方法的参数名。大家大概猜到是什么了吧?对!就是建一个自定义注解。
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
public @interface AOPLog4jAnnotation {
	String paramCollection();
}

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

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

唯一的好处是...只需要复制上面这行,然后遵循规则填写参数名。
唯二的好处是...日志格式统一。
完了,伤心了,感觉实用性不强,哎。  
算了,把代码都贴上吧,留着以后改进。
Spring配置:
	<bean id="helloService" class="com.aop.log4j.service.impl.HelloServiceImpl" />
	<bean id="aspect" class="com.aop.log4j.aspect.HelloAspect"/>
	<aop:config>
		<aop:pointcut id="pointcut" expression="execution(* com.aop.log4j.service.HelloService.*(..)))" />
		<aop:aspect ref="aspect">
			<aop:around pointcut-ref="pointcut" method="arround"/>
		</aop:aspect>
	</aop:config>

切面代码:
public class HelloAspect {
	private static final Logger logger = Logger.getLogger(HelloAspect.class);
	private static final String DOT = ".";//点号
	private static final String COMMA = ",";//逗号
	
	public void arround(ProceedingJoinPoint joinPoint) throws Throwable {
	    StringBuilder sb = new StringBuilder();
	    Object[] paramValues = joinPoint.getArgs();//获取参数值
	    String[] paramNames = new String[paramValues.length];
	    Method methods[] = joinPoint.getTarget().getClass().getMethods();
	    for (Method method : methods) {
		if(method.getName().equals(joinPoint.getSignature().getName())) {
                String paramCollection = method.getAnnotation
                      (AOPLog4jAnnotation.class).paramCollection();//获取注解值
				String[] names = paramCollection.split(COMMA);
				System.arraycopy(names, 0, paramNames, 0, names.length);
			}
		}
	    for (int i = 0; i < paramValues.length; i++) {
	    	sb.append(paramNames[i] + "=" + paramValues[i] + COMMA);
	    }
        //入参日志
	    logger.info(joinPoint.getTarget().getClass() + DOT + joinPoint.
                   getSignature().getName() + ",remote input:" 
                        + sb.toString().substring(0, sb.length() - 1));
	    try {
		   Object result = joinPoint.proceed();
           //出参日志
		   logger.info(joinPoint.getTarget().getClass() + DOT+joinPoint.
                   getSignature().getName() + ",remote output:" + result);
	    } catch (Exception e) {
		   logger.error(joinPoint.getTarget().getClass() + DOT+joinPoint.
                   getSignature().getName() + " invoke error");
	    }
	}
}

调用HelloService服务,输出:
[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.
[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.




已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [springaop 日志 java] 推荐:

SpringAOP实现自动生成日志 【基于java.lang.annotation约定】

- - ITeye博客
           项目中总要发布一下服务供系统内外调用,为了方便排查错误,入参出参都要以日志的形式记录下来. 传统做法:缺点一目了然,参数少的时候只能说还好,参数一多,烦不胜烦,浪费时间.            于是借鉴了AOP的思想,将日志功能做成一个切面,横向切入到业务逻辑前后(方法开始前和结束后).

SpringAOP拦截Controller,Service实现日志管理(自定义注解的方式)

- - 企业架构 - ITeye博客
         从业近二,三年了,第一次写博客,平时做做脚手架或者架构一些基础框架然后给大家使用或者自己总结翻译一些文档. 虽然是第一次但是我还是要拿Spring开刀. 希望张开涛,涛兄看到的时候不要喷我,给我一点指导.          首先我们为什么需要做日志管理,在现实的上线中我们经常会遇到系统出现异常或者问题.

Java GC日志查看

- - Java - 编程语言 - ITeye博客
Java中的GC有哪几种类型. 虚拟机运行在Client模式的默认值,打开此开关参数后,. 使用Serial+Serial Old收集器组合进行垃圾收集. 打开此开关参数后,使用ParNew+Serial Old收集器组合进行垃圾收集. 打开此开关参数后,使用ParNew+CMS+Serial Old收集器组合进行垃圾收集.

Java开发框架之日志

- - 后端技术杂谈 | 飒然Hang
日志在应用开发中是一个非常关键的部分. 有经验的工程师能够凭借以往的经验判断出哪里该打印日志、该以何种级别打印日志. 这样就能够在线上发生问题的时候快速定位并解决问题,极大的减少应用的运维成本. 使用控制台输出其实也算日志的一种,在容器中会打印到容器的日志文件中. 但是,控制台输出过于简单,缺乏日志中级别控制、异步、缓冲等特性,因此在开发中要杜绝使用控制台输出作为日志(System.out.println).

java日志,需要知道的几件事

- - Java - 编程语言 - ITeye博客
java日志,需要知道的几件事. 如果对于commons-loging 、log4j 、slf4j 、LogBack 等都已经非常清楚了,可以忽略本文. 几次解决日志冲突问题时对这几个概念的简单总结,希望对这块基础没有理解透的同学能有所帮助,当然如果对这块有更深刻理解的同学,也贡献出自己的知识和见解.

三个实例演示 Java Thread Dump 日志分析

- - 博客园_旁观者
jstack Dump 日志文件中的线程状态. dump 文件里,值得关注的线程状态有:. Deadlock(重点关注) . 执行中,Runnable   . Waiting on condition(重点关注) . Waiting on monitor entry(重点关注). 暂停,Suspended.

Log4j实现对Java日志的配置全攻略

- - CSDN博客互联网推荐文章
配置文件 Log4J配置文件的基本格式如下:. 举例:Testlog4.main(TestLog4.java: 10 ) 2. 在代码中初始化Logger: 1)在程序中调用BasicConfigurator.configure()方法:给根记录器增加一个ConsoleAppender,输出格式通过PatternLayout设为"%-4r [%t] %-5p %c %x - %m%n",还有根记录器的默认级别是Level.DEBUG.

Java程序员须知的七个日志管理工具

- - ImportNew
Splunk>Storm 日志管理工具有Splunk、Sumo Logic、LogStash、GrayLog、Loggly和PaperTrails等等,数不胜数. 日志就像石油,二十多年了我们一直想摆脱它,却一直没有做到. 为了处理日益增长的数据,近年来出现了一大批分析和管理日志的工具,开发和管理人员能够借助这些工具来了解增长的数据.

使用AOP与注解记录Java日志

- - ImportNew
有些时候,我想要把每个运行过的方法接收到的参数、返回值和执行时间等信息记录(通过slf4j 和 log4j)下来. 在AspectJ、jcabi-aspects和Java注解的帮助下我实现了这个想法. 在log4j中可以看到以下输出:. 接下来我们来看看它是如何工作的. 注解是Java 6中采用的一种技术( 译注:其实Java 5就有注解了).

java调用kettle api 操作日志写入到数据库表

- - 开源软件 - ITeye博客
//将step日志数据库配置名加入到变量集中. //StepLogTable使用的数据库连接名(上面配置的变量名). //设置Step日志的表名. //设置TransMeta的StepLogTable. 已有 0 人发表留言,猛击->> 这里<<-参与讨论. —软件人才免语言低担保 赴美带薪读研.