All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.dadiyang.autologging.aop.aspect.AbstractAspect Maven / Gradle / Ivy

package com.github.dadiyang.autologging.aop.aspect;

import com.github.dadiyang.autologging.aop.handler.JoinPointHandler;
import com.github.dadiyang.autologging.aop.util.SnowFlakeIdUtils;
import com.github.dadiyang.autologging.core.configuration.AutoLogConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 所有切面的基类,负责接管处理切点执行过程
 * 

* 子类负责定义切点方法和执行后对结果进行处理 * * @author dadiyang * @since 2020/3/1 */ @Slf4j @Aspect @RequiredArgsConstructor public abstract class AbstractAspect { private static final ThreadLocal ID_THREAD_LOCAL = new ThreadLocal<>(); private static final ThreadLocal STACK_THREAD_LOCAL = new ThreadLocal<>(); private AutoLogConfig autoLogConfig; private Map enableGetterMethods = new ConcurrentHashMap<>(8); /** * 抽象切点,由子类负责实现 */ @Pointcut() public abstract void pointcut(); /** * 获取切点信息处理器 * * @return 切点信息处理器 */ protected abstract JoinPointHandler getJoinPointHandler(); /** * 接管切面方法的执行过程,不拦截打了 com.github.dadiyang.aop.autologging.annotation.IgnoreLog 注解的类和方法 * * @param joinPoint 连接点信息 * @return 目标方法执行结果 * @throws Throwable 目标方法抛出的任何异常 */ @Around(value = "pointcut() && !@within(com.github.dadiyang.autologging.aop.annotation.IgnoreLog) && !@annotation(com.github.dadiyang.autologging.aop.annotation.IgnoreLog)") public Object globalAdvice(ProceedingJoinPoint joinPoint) throws Throwable { if (needIgnore()) { // 若切面需要被忽略,则直接执行并返回,不做后续处理 return joinPoint.proceed(); } if (ID_THREAD_LOCAL.get() == null) { ID_THREAD_LOCAL.set(SnowFlakeIdUtils.next()); } // 模拟线程栈 if (STACK_THREAD_LOCAL.get() == null) { STACK_THREAD_LOCAL.set(0); } // 方法执行时,栈深度加1 int depth = STACK_THREAD_LOCAL.get() + 1; STACK_THREAD_LOCAL.set(depth); // 目标方法执行结果 Object result = null; // 记录异常 Throwable throwable = null; // 目标方法执行的时间 long start = System.currentTimeMillis(); try { result = joinPoint.proceed(); } catch (Throwable th) { throwable = th; } finally { long handleJoinPointStart = System.nanoTime(); try { JoinPointHandler joinPointHandler = getJoinPointHandler(); if (joinPointHandler != null) { // 只记录方法执行的时间 long consumeTime = System.currentTimeMillis() - start; // 发生异常或者方法耗时大于或等于阈值时才处理 if (throwable != null || consumeTime >= autoLogConfig.getTimeConsumeThreshold()) { JoinPointInfo joinPointInfo = new JoinPointInfo(joinPoint, consumeTime, result, throwable); joinPointInfo.setThread(Thread.currentThread().getName()); joinPointInfo.setTraceId(ID_THREAD_LOCAL.get()); joinPointInfo.setStackDepth(depth - 1); joinPointInfo.setAspect(getAspectName()); joinPointInfo.setActualClassName(getActualClassName(joinPoint.getTarget().getClass())); result = joinPointHandler.handle(joinPointInfo); } } } finally { // 方法执行结束后栈深度减1 int curDepth = depth - 1; STACK_THREAD_LOCAL.set(curDepth); // 栈尝试为0表示调用链已结束,移除本线程的 ThreadLocal 变量,否则会导致内存泄漏 if (curDepth == 0) { STACK_THREAD_LOCAL.remove(); ID_THREAD_LOCAL.remove(); } if (log.isTraceEnabled()) { log.trace("autologging rt: {} ns", (System.nanoTime() - handleJoinPointStart)); } } } return result; } private boolean needIgnore() { if (autoLogConfig == null) { return false; } AutoLogConfig.AspectEnableConfig aspectEnableConfig = autoLogConfig.getAspectEnable(); // 没有配置则全部都不忽略 if (aspectEnableConfig == null) { return false; } // 检当前切面是否开启 Boolean enable = true; try { String capedAspectName = StringUtils.capitalize(getAspectName()); Method enableGetMethod = enableGetterMethods.computeIfAbsent(capedAspectName, name -> getEnableGetMethod(aspectEnableConfig, capedAspectName)); if (enableGetMethod == null) { // 没有则默认不忽略 return false; } // 是否打开 enable = (Boolean) enableGetMethod.invoke(aspectEnableConfig); } catch (Exception e) { log.warn("查检是否开启切面发生异常: {}, {}", getAspectName(), e.getMessage()); } // enable 必须明确等于 false 时才忽略 return enable != null && !enable; } private Method getEnableGetMethod(AutoLogConfig.AspectEnableConfig aspectEnableConfig, String capedAspectName) { Method[] methods = aspectEnableConfig.getClass().getMethods(); Method enableGetMethod = null; for (Method method : methods) { // 必须无参 if (method.getParameterCount() != 0) { continue; } // 必须 public if (!Modifier.isPublic(method.getModifiers())) { continue; } // 返回值必须为 boolean 或其包装类 if (method.getReturnType() != Boolean.class && method.getReturnType() != boolean.class) { continue; } // 因为配置项是 boolean 类型的,防止 getter 实现不一致,我们兼容 getXxx/isXxx/getIsXxx 三种写法 if (Objects.equals(("is" + capedAspectName), method.getName())) { enableGetMethod = method; break; } else if (Objects.equals(("get" + capedAspectName), method.getName())) { enableGetMethod = method; break; } else if (Objects.equals(("getIs" + capedAspectName), method.getName())) { enableGetMethod = method; break; } } return enableGetMethod; } /** * 获取切面的名称,默认为类名,子类可以通过覆盖此方法给定切面名称 * * @return 切面名称 */ protected String getAspectName() { return getClass().getSimpleName(); } protected String getActualClassName(Class aClass) { return aClass.getName(); } /** * 获取当前 traceId * * @return 当前 traceId */ public static Long getTraceId() { return ID_THREAD_LOCAL.get(); } /** * 获取当前栈深度 * * @return 当前栈深度 */ public static Integer getStackDepth() { return STACK_THREAD_LOCAL.get(); } @Resource public void setAutoLogConfig(AutoLogConfig autoLogConfig) { this.autoLogConfig = autoLogConfig; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy