`
JianFengLiang
  • 浏览: 13586 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

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

阅读更多
          项目中总要发布一下服务供系统内外调用,为了方便排查错误,入参出参都要以日志的形式记录下来。
传统做法:缺点一目了然,参数少的时候只能说还好,参数一多,烦不胜烦,浪费时间。

    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提供了现成的方法,但笔者觉得挺麻烦的,决定使用约定优于配置的方式来获取方法的参数名。大家大概猜到是什么了吧?对!就是建一个自定义注解。

@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 Object arround(ProceedingJoinPoint joinPoint) throws Throwable {
	    StringBuilder sb = new StringBuilder();
	    Object[] paramValues = joinPoint.getArgs();//获取参数值
	    String[] paramNames = new String[paramValues.length];
        Class<? extends Object> invokeClass = joinPoint.getTarget().getClass();
        String signatureName = joinPoint.getSignature().getName();
	    Method methods[] = invokeClass.getMethods();
	    for (Method method : methods) {
		if(method.getName().equals(signatureName)) {
                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(invokeClass  + DOT + signatureName + ",remote input:" 
                        + sb.toString().substring(0, sb.length() - 1));
	    try {
		   Object result = joinPoint.proceed();
           //出参日志
		   logger.info(invokeClass  + DOT + signatureName 
                   + ",remote output:" + result);
           return result;
	    } catch (Exception e) {
		   logger.error(invokeClass  + DOT + signatureName
                   + " invoke error");
	    }
        return null;
	}
}

调用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.
5
1
分享到:
评论
9 楼 kjj 2012-11-18  
和我的实现思路差不多,我是直接用aspectj这个插件记录的,sprign的aop总觉得没有原声的方便
8 楼 JianFengLiang 2012-11-18  
hitmit1314 写道
拜托,没有必要引入第三方包你用Spring干什么? 而且跟你说,Javassist叫做字节码读写框架,你要用到hibernate, 它本来就是required的包。即使你不用hibernate, spring 也用了字节码框架的,asm。 就是说,你已经有了这个资源,就是米有去用。而且字节码框架是直接读.class文件的,在有些时候,比起反射,classloader效果要好很多。

    是在搜自己遇到的问题搜到博主的文章的,想法很到位,十分感激。只是用了个贱贱的方法给你一些提示,呵呵,还请博主见谅,不与小辈计较,希望能帮助你改进你所说的缺点。另外, asm是访问者(Vister)模式的,比较难转过弯儿来



受教了!哈哈,谢谢哥们的指点,尽快改正~
7 楼 hitmit1314 2012-11-18  
拜托,没有必要引入第三方包你用Spring干什么? 而且跟你说,Javassist叫做字节码读写框架,你要用到hibernate, 它本来就是required的包。即使你不用hibernate, spring 也用了字节码框架的,asm。 就是说,你已经有了这个资源,就是米有去用。而且字节码框架是直接读.class文件的,在有些时候,比起反射,classloader效果要好很多。

    是在搜自己遇到的问题搜到博主的文章的,想法很到位,十分感激。只是用了个贱贱的方法给你一些提示,呵呵,还请博主见谅,不与小辈计较,希望能帮助你改进你所说的缺点。另外, asm是访问者(Vister)模式的,比较难转过弯儿来
6 楼 JianFengLiang 2012-10-06  
小树鹿鸣 写道
这个东东没啥实用,特别是形参的多变性, 公司项目还采用模板语言freemarker去解析参数,性能也经不起考验,还花了成员好多时间磨在上面,伤不起!还是自已去封装一套API,格式可以自定义在properties文件中,使用占位符, 这样来得简单。

多谢您的建议,确实不实用,权当一个想法,抛砖引玉啦。
PS:哈哈 WEB-INF\lib 你都去看了~太仔细了,示例里面是没用到freemarker的,忘记删了。不过公司的项目用的都是freemarker。可能为了省事吧,不甚理解。
5 楼 小树鹿鸣 2012-10-06  
这个东东没啥实用,特别是形参的多变性, 公司项目还采用模板语言freemarker去解析参数,性能也经不起考验,还花了成员好多时间磨在上面,伤不起!还是自已去封装一套API,格式可以自定义在properties文件中,使用占位符, 这样来得简单。
4 楼 tywo45 2012-10-04  
不用测试,目测一把就知道性能很差,博主赶紧给个高性能版本的。哈哈
3 楼 JianFengLiang 2012-10-03  
cue2008 写道
你有压测过性能吗

没有 目测性能会很差 反射、循环等 公司项目有现成的一套 想自己先写一个再去研究公司的 呵呵
2 楼 cue2008 2012-10-03  
你有压测过性能吗
1 楼 kjj 2012-10-03  
由于java的反射是不能获取方法的参数名的 :roll:  :roll:  :roll:  :roll:  :roll:  :roll: 

相关推荐

    org.aspectj.lang.annotation.Around所需要的包

    综上所述,要解决“java.lang.ClassNotFoundException: org.aspectj.lang.annotation.Around”错误,确保这三个jar包已经正确地添加到项目的类路径中,并且正确配置了Spring的AOP设置。通过这种方式,你可以充分利用...

    Spring的AOP实现的日志功能案例.zip

    当添加Studnet的信息的时候实现日志的插入 Spring的AOP实现的日志功能案例.zip Spring的AOP实现的日志功能案例.zip Spring的AOP实现的日志功能案例.zip Spring的AOP实现的日志功能案例.zip Spring的AOP实现的日志...

    JAVA 中Spring aop 实现日志记载

    在Java开发中,Spring AOP(面向切面编程)是一个强大的功能,用于实现日志记录。AOP允许我们在不修改原有代码的情况下,插入新的行为,比如日志记录,事务管理等。下面将详细介绍如何在Spring框架中使用AOP来实现...

    spring aop 自定义注解保存操作日志到mysql数据库 源码

    4、想看spring aop 注解实现记录系统日志并入库等 二、能学到什么 1、收获可用源码 2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑实现 (需要知道原理的请看spring aop源码,此处不做赘述) 3、...

    基于注解实现SpringAop

    基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop

    反射实现 AOP 动态代理模式(Spring AOP 的实现 原理) - Java 例子 -

    Spring框架是Java中实现AOP的一个流行工具,它通过动态代理机制实现了这一功能。本文将深入探讨Spring AOP的实现原理,以及如何使用反射来实现动态代理模式。 首先,我们需要了解AOP的基本概念。AOP的核心思想是切...

    spring AOP 切面日志 分层打日志

    在这里,我们重点关注如何利用Spring AOP实现分层日志记录。 **一、Spring AOP基本概念** 1. **切面(Aspect)**: 切面是封装了横切关注点的模块,例如日志记录就是一个横切关注点,它横跨多个对象和类。 2. **通知...

    SpringAOP切面编程依赖jar包.rar

    学习Spring开发的AOP面向切面编程时所需要的jar包,包括com.springsource.net.sf.cglib-2.2.0.jar com.springsource.org.aopalliance-1.0.0.jar com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

    Spring AOP 16道面试题及答案.docx

    总的来说,Spring AOP通过代理和通知机制,实现了横切关注点的模块化,使得业务逻辑与系统服务(如日志、事务等)解耦,提高了代码的可读性和可维护性。同时,引介功能进一步增强了切面的功能,可以为对象动态地添加...

    Spring AOP实现机制

    - 当目标对象实现了至少一个接口时,Spring会使用JDK的java.lang.reflect.Proxy类创建一个代理对象。 - 代理对象在调用实际方法前后,会插入相应的通知代码,从而实现AOP功能。 - **CGLIB代理**: - 如果目标...

    springboot spring aop 拦截器注解方式实现脱敏

    在Spring Boot应用中,Spring AOP(面向切面编程)是一种强大的工具,它允许我们创建横切关注点,如日志记录、权限检查等,这些关注点可以被编织到应用程序的多个点上,而无需侵入核心业务逻辑。在本案例中,我们将...

    spring-aop.jar

    在spring-aop.jar中,`org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator`类负责自动创建代理并织入切面。 三、Spring AOP的使用 在实际应用中,我们可以利用Spring AOP进行日志记录、...

    Spring AOP 日志管理 实例

    Spring AOP 日志管理 实例LoggingThrowsAdvice.java

    反射实现 AOP 动态代理模式(Spring AOP 的实现原理)

    面向切面编程(AOP)是一种编程范式,旨在将横切关注点(如日志、安全等)与业务逻辑分离,从而提高模块化。...利用Java反射机制和Spring AOP框架,开发者可以方便地实现AOP,从而提升代码的模块化和可维护性。

    基于java的企业级应用开发:Spring AOP简介.ppt

    Spring AOP提供了两种实现方式:一是基于代理(Proxy-based AOP),二是基于字节码(Bytecode-based AOP)。基于代理的方式主要是使用Java动态代理或CGLIB生成代理对象;基于字节码的实现则依赖于ASM库,如AspectJ的...

    spring-aop-5.2.0.RELEASE-API文档-中文版.zip

    标签:springframework、spring、aop、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译...

    Java进阶之SpringAOP应用共16页.pdf.zi

    本资料"Java进阶之SpringAOP应用共16页.pdf"深入探讨了Spring AOP在实际开发中的应用和实现原理,旨在提升Java开发者的技能水平。 首先,理解AOP的基本概念至关重要。AOP是一种编程范式,它将关注点分离为不同的...

    springAop默认代理方式.zip

    4. **代理模式的创建**:Spring AOP 使用`org.springframework.aop.framework.ProxyFactoryBean`或`@EnableAspectJAutoProxy`注解来配置代理。`ProxyFactoryBean`是XML配置方式,而`@EnableAspectJAutoProxy`是基于...

    spring-aop-5.0.8.RELEASE-API文档-中英对照版.zip

    标签:springframework、spring、aop、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准...

Global site tag (gtag.js) - Google Analytics