学习使用Spring AOP写方法Debug日志
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;}}