`

学习使用Spring AOP写方法Debug日志

阅读更多
package org.allenz.tadths.debug;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 日志注解,通过Spring AOP打印被注解的方法的参数、返回值和异常信息。<br>
 * 
 * @author Allenz
 * @version 1.0
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
	boolean before() default false;

	boolean afterReturning() default false;

	boolean afterThrowing() default true;
}


package org.allenz.tadths.debug;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;

/**
 * 日志注解实现。
 * 
 * @author Allenz
 * @version 1.0
 */
public class LogAdvice {

	private Class<?> targetClass;
	private Method targetMethod;
	private Logger logger;
	private boolean hasLogAnnotation;
	private boolean before;
	private boolean afterReturning;
	private boolean afterThrowing;
	private String beforeLog;

	/**
	 * 在日志打印方法参数。
	 * 
	 * @param jp
	 *            连接点
	 */
	public void before(JoinPoint jp) {
		Logger logger = this.getLogger(jp);
		if (!logger.isDebugEnabled()) {
			return;
		}
		if (!this.hasLogAnnotation(jp)) {
			return;
		}
		StringBuilder logBuilder = new StringBuilder();
		String methodName = jp.getSignature().getName();
		logBuilder.append("Invoke ").append(methodName).append("(");
		Object[] args = jp.getArgs();
		if (args.length > 0) {
			for (int i = 0; i < args.length; i++) {
				logBuilder.append(args[i]).append(",");
			}
			logBuilder.deleteCharAt(logBuilder.length() - 1);
		}
		logBuilder.append(")");
		// "Invoke MethodName(ParamValue1,ParamValue1...)"
		String log = logBuilder.toString();
		this.beforeLog = log;
		if (this.before) {
			logger.debug(log);
		}
	}

	/**
	 * 在日志打印方法返回值。
	 * 
	 * @param jp
	 *            连接点
	 * @ret 返回值
	 */
	public void afterReturning(JoinPoint jp, Object ret) {
		Logger logger = this.getLogger(jp);
		if (!logger.isDebugEnabled()) {
			return;
		}
		if (!this.hasLogAnnotation(jp)) {
			return;
		}
		StringBuilder logBuilder = new StringBuilder();
		logBuilder.append("Return ").append(ret);
		// "Return ReturnValue"
		String log = logBuilder.toString();
		// 打印方法参数
		if (!this.before) {
			logger.debug(this.beforeLog);
		}
		if (this.afterReturning) {
			logger.debug(log);
		}
	}

	/**
	 * 在日志打印方法异常。
	 * 
	 * @param jp
	 *            连接点
	 * @param e
	 *            异常
	 */
	public void afterThrowing(JoinPoint jp, Throwable e) {
		Logger logger = this.getLogger(jp);
		if (!this.hasLogAnnotation(jp)) {
			return;
		}
		if (!this.afterThrowing) {
			return;
		}
		StringBuilder logBuilder = new StringBuilder();
		logBuilder.append("Throws ").append(e.getClass().getName()).append("(")
				.append(e.getLocalizedMessage()).append(")");
		// "Throws ExceptionClassName(ExceptionMessage)"
		String log = logBuilder.toString();
		// 打印方法参数
		if (!this.before) {
			logger.error(this.beforeLog);
		}
		logger.error(log);
	}

	/**
	 * 获取被增强的对象的类型。
	 * 
	 * @param jp
	 *            连接点
	 * @return 对象的类型
	 */
	private Class<?> getTargetClass(JoinPoint jp) {
		if (this.targetClass == null) {
			this.targetClass = jp.getTarget().getClass();
		}
		return this.targetClass;
	}

	/**
	 * 获取被增强的方法。
	 * 
	 * @param jp
	 *            连接点
	 * @return 方法
	 */
	private Method getTargetMethod(JoinPoint jp) {
		if (this.targetMethod == null) {
			MethodSignature methodSignature = (MethodSignature) jp
					.getSignature();
			this.targetMethod = methodSignature.getMethod();
		}
		return this.targetMethod;
	}

	/**
	 * 从Logger工厂获取被增强对象的Logger。
	 * 
	 * @param jp
	 *            连接点
	 * @return Logger
	 */
	private Logger getLogger(JoinPoint jp) {
		if (this.logger == null) {
			this.logger = LoggerFactory.getLogger(this.getTargetClass(jp));
		}
		return this.logger;
	}

	/**
	 * 检查被增强的方法是否拥有日志注解。
	 * 
	 * @param jp
	 *            连接点
	 * @return 拥有返回真,没有返回假
	 */
	private boolean hasLogAnnotation(JoinPoint jp) {
		if (!this.hasLogAnnotation) {
			// 优先使用方法注解
			Log logAnno = AnnotationUtils.findAnnotation(this.getTargetMethod(jp),
					Log.class);
			// 找不到方法注解,使用类注解
			if (logAnno == null) {
				logAnno = AnnotationUtils.findAnnotation(this.getTargetClass(jp),
						Log.class);
			}
			if (logAnno != null) {
				this.hasLogAnnotation = true;
				this.before = logAnno.before();
				this.afterReturning = logAnno.afterReturning();
				this.afterThrowing = logAnno.afterThrowing();
			}
		}
		return this.hasLogAnnotation;
	}

}
分享到:
评论

相关推荐

    spring aop 切面添加日志

    通过这个项目,我们可以学习到如何在Spring AOP中实现日志记录,这不仅可以帮助我们调试和监控应用程序,还可以为未来的维护提供宝贵的线索。同时,这也是理解和实践面向切面编程的一个很好的起点。

    spring AOP 切面日志 分层打日志

    在Spring框架中,AOP(面向切面编程)是一种强大的工具,它允许我们在不修改源代码的情况下,对程序进行横向关注点的插入,比如日志记录、事务管理、权限检查等。在这里,我们重点关注如何利用Spring AOP实现分层...

    Spring之AOP在鉴权和日志记录中的应用

    3. **日志框架集成**:Spring AOP可以与各种日志框架(如Log4j、Logback、SLF4J)配合使用,只需配置合适的日志适配器。 4. **动态日志配置**:通过Spring的Profile特性,可以根据环境动态调整日志输出级别。 **五...

    Spring Mvc AOP通过注解方式拦截controller等实现日志管理

    本教程将详细介绍如何利用注解来配置和使用AOP来拦截Controller层的方法,以便记录执行过程中的相关信息,实现日志管理。 一、Spring AOP基础 AOP是Spring框架的核心组件之一,它允许程序员定义“切面”,这些切面...

    Spring Aop+Log4j 动态日志

    在IT行业中,Spring AOP(面向切面编程)和Log4j是两个非常重要的工具,它们在实际开发中起着至关重要...读者可以通过学习这些材料,更深入地理解Spring AOP和Log4j的结合使用,以及如何在实际项目中应用动态日志功能。

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

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

    spring aop实现日志功能 开发技术-其它

    下面我们将深入探讨如何使用Spring AOP来实现日志功能,以及这一技术的核心概念和应用场景。 首先,Spring AOP是Spring框架的一个核心特性,它允许开发者通过声明式的方式定义横切关注点,如日志、事务管理、性能...

    利用 spring annotation AOP 反射 记录日志

    下面我们将详细探讨如何利用Spring的注解AOP和反射来实现日志记录。 首先,我们需要理解Spring的AOP注解。最常用的两个注解是`@Aspect`和`@Pointcut`。`@Aspect`用于定义一个切面类,而`@Pointcut`则用来声明一个...

    Spring Boot项目中使用Logback日志与使用AOP拦截请求日志信息

    本教程将深入探讨如何在Spring Boot中集成Logback,并利用AOP(面向切面编程)来拦截并记录请求日志信息。 首先,让我们了解Spring Boot如何配置Logback。在Spring Boot项目中,日志配置默认位于`src/main/...

    Spring MVC AOP通过注解方式拦截Controller等实现日志管理demo版本2

    通过这个示例,你可以学习如何在Spring MVC项目中使用AOP注解进行日志管理,从而更好地理解和实践面向切面编程,提高代码的维护性和可扩展性。同时,这也是一个很好的起点,帮助你进一步探索Spring AOP在事务管理、...

    springaop学习

    ### Spring AOP 学习知识点详解 #### 一、Spring AOP 原理 **Spring AOP**(面向切面编程)是 Spring 框架中的一个关键特性,它提供了一种优雅的方式来处理横切关注点(cross-cutting concerns)。在实际应用中,...

    Spring之AOP注解之引入通知

    在Spring框架中,AOP(面向切面编程)是一种强大的工具,它允许程序员将关注点分离,例如日志记录、事务管理等,从核心业务逻辑中解耦出来。本篇文章将深入探讨Spring AOP中的注解引入通知,以及如何利用它们来增强...

    spring-aop-aroud-demo.zip

    在本示例中,我们探讨的是如何在Spring Boot项目中使用Spring AOP(面向切面编程)实现环绕通知,以自动记录日志的功能。Spring AOP是Spring框架的一部分,它允许我们在不修改源代码的情况下,对应用程序进行横切...

    Spring的aopjar包

    `log4j`是一个广泛使用的开源日志框架,它提供了灵活的日志记录控制,包括不同的日志级别(如DEBUG、INFO、WARN、ERROR、FATAL),以及自定义日志格式和输出目的地(如控制台、文件、网络等)。Spring与log4j的整合...

    spring_aop麻雀

    在IT行业中,Spring框架是一个广泛使用的Java企业级应用开发框架,而AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的一个重要组成部分。本项目“spring_aop麻雀”显然旨在展示如何在小型项目中...

    使用Spring 完成转账业务添加日志功能

    在`logBefore()`和`logAfter()`方法中,我们可以使用SLF4J API(Spring推荐的日志抽象层)来记录日志,例如: ```java import org.slf4j.Logger; import org.slf4j.LoggerFactory; private final Logger logger = ...

    Spring - 3 AOP

    通过上述步骤,我们成功地在Spring中实现了AOP,不仅能够记录方法执行的日志,还能够保持业务逻辑代码的纯净,避免了混杂其他非核心业务逻辑代码。 #### 四、总结 AOP是Spring框架中的一个重要组成部分,通过AOP...

    spring简单注解+log4j记录日志

    综上所述,"spring简单注解+log4j记录日志"这个主题涵盖了Spring框架中的注解使用、Log4j日志系统以及AOP的应用。通过学习这些内容,初学者可以更好地理解和实践Spring框架,同时提高代码的可维护性和调试效率。在...

    利用Spring机制记录系统日志

    我们还可以使用`&lt;aop:pointcut&gt;`定义切入点表达式,指定哪些方法需要被拦截,然后在`&lt;aop:advisor&gt;`或`&lt;aop:around&gt;`中引用这个切入点,将`AutoLogAdvice`应用到这些方法上。 为了确保日志记录的灵活性和可配置性,...

Global site tag (gtag.js) - Google Analytics