增加日志输出标识
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface MDC {
}
切面:
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.slf4j.MDC;
@Slf4j
public abstract class MdcInterceptor {
protected final static String LOG_ID = "logId";
@Pointcut("execution(* com.noob.api..*.*(..)) || @annotation(com.noob.aspectj.MDC)")
public void pointCut() {
// do nothings
};
@Around(value = "pointCut()")
public Object invoke(ProceedingJoinPoint point) throws Throwable {
Object result;
try {
setTradeId();
result = point.proceed(point.getArgs());
removeTraceId();
} catch (Throwable throwable) {
throw throwable;
} finally {
removeTraceId();
}
return result;
}
/**
* 璁剧疆traceId
*/
public static void setTradeId() {
try {
MDC.put(LOG_ID, UUID.randomUUID().toString().replace("-", ""));
} catch (Exception e) {
log.error("set log no exception", e);
}
}
/**
* remove traceId
*/
public static void removeTraceId() {
try {
MDC.remove(LOG_ID);
} catch (Exception e) {
log.error("remove log no exception", e);
}
}
}
@Sync继承MDC上下文
在使用@Sync时,Spring默认提供的TaskExecutor下的ThreadPoolTaskExecutor无法支持MDC在线程切换时上下文内容的继承。因为MDC本质上使用ThreadLocal来保存上下文。
需要注意的是:切面的织入一定要符合【外部调入】的原则!
解决方法:
重写ThreadPoolTaskExecutor,在callable(真实处理过程)前注入父线程内容。
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org