我认为没有直接的方法可以改变这一点。想到的两个替代方案是:
方式#1:包装所有Runnable
s
引入一个抽象类,它将MDC
从原始类复制Thread
到新类Thread
并使用它而不是Runnable
public abstract class MdcAwareRunnable implements Runnable
{
private Map<String, String> originalMdc;
public MdcAwareRunnable()
{
this.originalMdc = MDC.getCopyOfContextMap();
}
@Override
public void run()
{
MDC.setContextMap(originalMdc);
runImpl();
}
protected abstract void runImpl();
/**
* In case some Runnable comes from external API and we can't change that code we can wrap it anyway.
*/
public static MdcAwareRunnable wrap(Runnable runnable)
{
return new MdcAwareRunnable()
{
@Override
protected void runImpl()
{
runnable.run();
}
};
}
}
如果某些Runnable
来自您无法更改该代码的外部 API,请使用wrap
辅助方法。
缺点:需要分析和更改整个代码。
方式#2:弄乱 slf4j 内部
恢复在该提交之前使用的原始LogbackMDCAdapter
实现,InheritableThreadLocal
并将其以其他名称放在代码中的某个位置。然后在启动附近的某个地方使用反射来覆盖MDC.mdcAdapter属性和该自定义实现的实例。这显然是一个肮脏的黑客,但与#1相比,它节省了很多麻烦。
注意:出于性能原因,它会从现有版本继承您的复活版本,LogbackMDCAdapter
并使用旧实现覆盖所有方法。有关详细信息,请参阅LoggingEvent.java和LogbackMDCAdapter.getPropertyMap
内部方法。
方式#3:弄乱logback jar(甚至更奇怪的选择)
这对我来说听起来是一个非常糟糕的计划,但为了完整起见,它就是这样。
再次复活原始LogbackMDCAdapter
文件,但这次不要重命名,编译它并覆盖 logback.jar 中的那个 .class 文件。
或者通过重命名来复活原始LogbackMDCAdapter
文件,从 logback.jar 中删除 .class 文件org.slf4j.impl.StaticMDCBinder
并添加您自己的类,该类将返回LogbackMDCAdapter
logback.jar 或您的代码的复活版本。MDC
似乎按名称绑定到该类以创建MDCAdapter
要使用的实现。
或者,您可以通过使用ClassLoader
映射org.slf4j.impl.StaticMDCBinder
到您的类而不是 logback.jar 中的类来实现类似的结果。注意:这可能是不可能在将添加自己的自定义类加载器的 Web 容器中实现的。