0

我有一个严重的问题,TomcatLoadTimerWeaverLog4j不知道如何解决它。

我正在使用以下内容:

  • 雄猫 8
  • Spring 框架 4.1.2
  • 日志4j 2.1
  • SLF4J 1.7.7
  • EclipseLink 2.5.2

所有日志都被路由到 SLF4J,我使用 Log4j 2.1 作为日志后端。web.xmlLog4j 被配置为从通过log4jConfigurationcontext-param指定的非标准位置获取其配置文件。在Log4jServletContainerInitializerwebapp 启动时正确配置 Log4j。一旦 Spring 配置了TomcatLoadTimeWeaver.

我想使用 EclipseLink 的加载时间编织,所以我将它添加到我的应用程序上下文中:

<context:load-time-weaver/>

问题是这样的:一旦 SpringTomcatLoadTimeWeaver通过向 Tomcat's 添加转换器来注册 a WebappClassLoader,随后第一次尝试通过 SLF4J 记录某些内容会导致 Log4j 被隐式重新初始化:因为我的配置文件不在标准位置(=类路径)我得到错误:

找不到 log4j2 配置文件

从那一刻起,所有日志调用都不再正确处理(= 以我在 MY 中指定的方式log4j.xml),并且我为 Commons Logging 和 JUL 精心配置的 SLF4J+Log4j+bridges 完全被破坏了。

似乎添加类加载器转换器正在重置 Log4j 中的某些内容,因此它需要重新配置自身:我花了几个小时试图更好地理解这个问题,但如果没有对 Log4j 的深入了解,这并不容易内部结构。

将我log4j.xml移到log4j2.xml类路径根目录不是我可以轻易做到的事情(出于部署原因),并且无论如何我都不确定不受我控制的 Log4j 的隐式重新配置是否会是一件好事。

也许加载时间编织器的早期配置(在 Log4j 第一次配置自身之前)会成功,但我不确定如何做到这一点,因为 Log4j 通常应该在 Spring 本身之前设置。

任何建议表示赞赏。

更多详细信息

实际上,问题不会在Spring DefaultContextLoadTimeWeaver(带有由 EclipseLink(由 触发)实际创建的本机。因此,我的解决方法是注册一个拦截 的初始化并强制再次运行,从而使用我的 webapp 设置重新配置 Log4j。不过,我最终得到了一个可怕的 hack,因为那些 Log4j 类充满了默认和受保护的方法,我不得不使用反射并将我的 bean 后处理器放在包中以使其工作。TomcatLoadTimeWeaverLocalContainerEntityManagerFactoryBeanEntityManagerFactoryorg.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet()org.springframework.context.weaving.DefaultContextLoadTimeWeaver.addTransformer(ClassFileTransformer)EntityManagerFactoryorg.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory()BeanPostProcessorLocalContainerEntityManagerFactoryBeanorg.apache.logging.log4j.web.Log4jWebInitializerImpl.start()org.apache.logging.log4j.core

欢迎提出更智能的解决方案/建议/替代方法。

实际原因

我进一步调试了整个系统并找出了这个问题的原因。我为此打开了 LOG4J2-903。简而言之,Log4j 使用类加载器toString()值在映射中搜索当前日志上下文。由于 Tomcat 的WebappClassLoader.toString()方法在您注册转换器时发生更改,因此 Log4j 无法检索先前配置的上下文并在 EclipseLink+Spring 注册加载时间编织器转换器后立即创建一个新的上下文... :-(

4

1 回答 1

0

此问题的解决方案是升级到 Log4j 2.2,其中包含对LOG4J2-903的修复。

于 2015-03-02T15:03:46.647 回答