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实现分层...
3. **日志框架集成**:Spring AOP可以与各种日志框架(如Log4j、Logback、SLF4J)配合使用,只需配置合适的日志适配器。 4. **动态日志配置**:通过Spring的Profile特性,可以根据环境动态调整日志输出级别。 **五...
本教程将详细介绍如何利用注解来配置和使用AOP来拦截Controller层的方法,以便记录执行过程中的相关信息,实现日志管理。 一、Spring AOP基础 AOP是Spring框架的核心组件之一,它允许程序员定义“切面”,这些切面...
在IT行业中,Spring AOP(面向切面编程)和Log4j是两个非常重要的工具,它们在实际开发中起着至关重要...读者可以通过学习这些材料,更深入地理解Spring AOP和Log4j的结合使用,以及如何在实际项目中应用动态日志功能。
在Spring Boot应用中,Spring AOP(面向切面编程)是一种强大的工具,它允许我们创建横切关注点,如日志记录、权限检查等,这些关注点可以被编织到应用程序的多个点上,而无需侵入核心业务逻辑。在本案例中,我们将...
下面我们将深入探讨如何使用Spring AOP来实现日志功能,以及这一技术的核心概念和应用场景。 首先,Spring AOP是Spring框架的一个核心特性,它允许开发者通过声明式的方式定义横切关注点,如日志、事务管理、性能...
下面我们将详细探讨如何利用Spring的注解AOP和反射来实现日志记录。 首先,我们需要理解Spring的AOP注解。最常用的两个注解是`@Aspect`和`@Pointcut`。`@Aspect`用于定义一个切面类,而`@Pointcut`则用来声明一个...
本教程将深入探讨如何在Spring Boot中集成Logback,并利用AOP(面向切面编程)来拦截并记录请求日志信息。 首先,让我们了解Spring Boot如何配置Logback。在Spring Boot项目中,日志配置默认位于`src/main/...
通过这个示例,你可以学习如何在Spring MVC项目中使用AOP注解进行日志管理,从而更好地理解和实践面向切面编程,提高代码的维护性和可扩展性。同时,这也是一个很好的起点,帮助你进一步探索Spring AOP在事务管理、...
### Spring AOP 学习知识点详解 #### 一、Spring AOP 原理 **Spring AOP**(面向切面编程)是 Spring 框架中的一个关键特性,它提供了一种优雅的方式来处理横切关注点(cross-cutting concerns)。在实际应用中,...
在Spring框架中,AOP(面向切面编程)是一种强大的工具,它允许程序员将关注点分离,例如日志记录、事务管理等,从核心业务逻辑中解耦出来。本篇文章将深入探讨Spring AOP中的注解引入通知,以及如何利用它们来增强...
在本示例中,我们探讨的是如何在Spring Boot项目中使用Spring AOP(面向切面编程)实现环绕通知,以自动记录日志的功能。Spring AOP是Spring框架的一部分,它允许我们在不修改源代码的情况下,对应用程序进行横切...
`log4j`是一个广泛使用的开源日志框架,它提供了灵活的日志记录控制,包括不同的日志级别(如DEBUG、INFO、WARN、ERROR、FATAL),以及自定义日志格式和输出目的地(如控制台、文件、网络等)。Spring与log4j的整合...
在IT行业中,Spring框架是一个广泛使用的Java企业级应用开发框架,而AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的一个重要组成部分。本项目“spring_aop麻雀”显然旨在展示如何在小型项目中...
在`logBefore()`和`logAfter()`方法中,我们可以使用SLF4J API(Spring推荐的日志抽象层)来记录日志,例如: ```java import org.slf4j.Logger; import org.slf4j.LoggerFactory; private final Logger logger = ...
通过上述步骤,我们成功地在Spring中实现了AOP,不仅能够记录方法执行的日志,还能够保持业务逻辑代码的纯净,避免了混杂其他非核心业务逻辑代码。 #### 四、总结 AOP是Spring框架中的一个重要组成部分,通过AOP...
综上所述,"spring简单注解+log4j记录日志"这个主题涵盖了Spring框架中的注解使用、Log4j日志系统以及AOP的应用。通过学习这些内容,初学者可以更好地理解和实践Spring框架,同时提高代码的可维护性和调试效率。在...
我们还可以使用`<aop:pointcut>`定义切入点表达式,指定哪些方法需要被拦截,然后在`<aop:advisor>`或`<aop:around>`中引用这个切入点,将`AutoLogAdvice`应用到这些方法上。 为了确保日志记录的灵活性和可配置性,...